package com.yaodian100.ec.product.service.impl;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.betwixt.io.BeanWriter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.entity.UserPermission;
import com.yaodian100.core.admin.entity.Permission.Type;
import com.yaodian100.core.admin.service.UserService;
import com.yaodian100.core.admin.utils.AdminHelper;
import com.yaodian100.core.batch.service.BatchJobService;
import com.yaodian100.core.cache.exception.CacheException;
import com.yaodian100.core.cache.service.CacheService;
import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.dao.impl.CriteriaInRlike;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.BaseManager;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.DateUtil;
import com.yaodian100.core.common.utils.ServerValue;
import com.yaodian100.core.logger.service.LogService;
import com.yaodian100.ec.category.entity.Category;
import com.yaodian100.ec.category.service.CategoryService;
import com.yaodian100.ec.common.EcConstant;
import com.yaodian100.ec.product.dao.AddOnProductDao;
import com.yaodian100.ec.product.dao.SpecificationInventoryDao;
import com.yaodian100.ec.product.entity.AddOnProduct;
import com.yaodian100.ec.product.entity.AddOnProductPage;
import com.yaodian100.ec.product.entity.Brand;
import com.yaodian100.ec.product.entity.ProdCatRC;
import com.yaodian100.ec.product.entity.ProdCatSE;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.entity.ProductCategory;
import com.yaodian100.ec.product.entity.ProductPage;
import com.yaodian100.ec.product.entity.ProductPromotionFlag;
import com.yaodian100.ec.product.entity.Specification;
import com.yaodian100.ec.product.entity.SpecificationInventory;
import com.yaodian100.ec.product.entity.SpecificationMajor;
import com.yaodian100.ec.product.entity.ViewPickProduct;
import com.yaodian100.ec.product.entity.VirtualProduct;
import com.yaodian100.ec.product.remote.RemoteProduct;
import com.yaodian100.ec.product.remote.RemoteSpecification;
import com.yaodian100.ec.product.service.ProductService;
import com.yaodian100.ec.proposeproduct.entity.ProposeProduct;
import com.yaodian100.ec.shelf.entity.Shelf;
import com.yaodian100.ec.shelf.service.ShelfService;
import com.yaodian100.ec.supplierapply.entity.SupplierApply;
import com.yaodian100.ec.supplierapply.service.SupplierApplyService;

public class ProductServiceImpl extends DomainServiceImpl<Product> implements ProductService {
	private ObjectDao<Specification> specificationDao;
	/* supplier */
	private ObjectDao<SupplierApply> supplierApplyDao;
	@Autowired
	private SupplierApplyService supplierApplyService;
	private ObjectDao<ProductCategory> productcategoryDao;
	private ObjectDao<Category> categoryDao;
	private ObjectDao<VirtualProduct> virtualproductDao;
	private ObjectDao<ProposeProduct> proposeproductDao;
	private ShelfService shelfService;
	private ObjectDao<Brand> brandDao;
	private ObjectDao<Shelf> shelfDao;
	private ObjectDao<ProductPromotionFlag> productPromotionFlagDao;
	private SpecificationInventoryDao specificationinventoryDao;// 獨立的dao
	private AddOnProductDao addonproductDao;// 獨立的dao
	private ObjectDao<ViewPickProduct> viewPickProductDao;
	private ObjectDao<ProductPage> productPageDao;

	private CacheService<Map> specCache;
	private CacheService<Map> addOnProductCache;

	private final String[] defaultSort = new String[] { "modifyDate", "createDate" };
	@Resource
	private BatchJobService batchJobService;
	@Resource
	private LogService logService;
	@Resource
	private BaseManager baseManager;
	private CacheService<Map> specificationCache;
	@Autowired
	private JdbcTemplate t;
	@Autowired
	private UserService userService;
	@Autowired
	private CategoryService categoryService;
	private final String STRING_SYMBOL = "/";

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#copyProduct(com.yaodian100.ec.product.entity.Product,
	 * com.yaodian100.ec.product.entity.ProductPromotionFlag)
	 */

	@Transactional(readOnly = false)
	public Product copyProduct(String copyProductId) throws CoreException, IllegalAccessException,
			InvocationTargetException {
		Product newProduct = new Product();
		Product product = getDao().get(copyProductId);
		ProductPromotionFlag newFlag = new ProductPromotionFlag();
		ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
		BeanUtils.copyProperties(newProduct, product);
		BeanUtils.copyProperties(newFlag, product.getProductPromotionFlag());
		newProduct.setProductId(getProposeProductIdNo());
		newFlag.setProductId(newProduct.getProductId());
		Specification newSpec = null;
		List<Specification> specs = product.getSpecifications();
		List<Specification> newSpecs = new ArrayList<Specification>();
		for (Specification spec : specs) {
			newSpec = new Specification();
			BeanUtils.copyProperties(newSpec, spec);
			newSpec.setProductId(newProduct.getProductId());
			newSpecs.add(newSpec);
		}

		Collection<SupplierApply> suppliers = product.getSuppliers();
		List<SupplierApply> newsuppliers = new ArrayList<SupplierApply>();
		if (null != suppliers) {
			Iterator iter = suppliers.iterator();
			while (iter.hasNext()) {
				newsuppliers.add((SupplierApply) iter.next());
			}
		}
		newProduct.setSuppliers(newsuppliers);
		newProduct.setSpecifications(newSpecs);
		newProduct.setProductPromotionFlag(newFlag);

		if (null == newProduct.getProductId()) {
			newProduct.setProductId(getProposeProductIdNo());
		}

		String orderNotice = product.getProductOrderNotice();
		String description = product.getProductDescription();
		String brief = product.getProductBrief();
		String details = product.getProductDetails();

		// // 将特色去除html code存入db
		if (StringUtils.isNotBlank(brief)) {
			newProduct.setProductBrief(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(brief,
					true), 0, 50));
		}
		// 将活动说明去除html code存入db
		if (StringUtils.isNotBlank(description)) {
			newProduct.setProductDescription(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(
					description, true), 0, 50));
		}
		// 将活动规格内容去除html code存入db
		if (StringUtils.isNotBlank(details)) {
			newProduct.setProductDetails(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(
					details, true), 0, 50));
		}
		newProduct.setProductOrderNotice("");// 购物须知不须存到db
		newProduct = getDao().saveOrUpdate(newProduct);

		// 新规格就新增一笔库存
		CommonCriteria criteriaSpec = new CommonCriteria();
		criteriaSpec.addEq("productId", newProduct.getProductId());
		SpecificationInventory specificationInventory;
		for (Specification spec : newSpecs) {
			specificationInventory = new SpecificationInventory();
			specificationInventory.setProductId(newProduct.getProductId());
			specificationInventory.setSpecId(spec.getSpecificationId());
			specificationInventory.setAvailableInventory(0);
			specificationInventory.setCancelInventory(0);
			specificationInventory.setSoldInventory(0);
			saveSpecificationInventory(specificationInventory);
		}

		// 储存成檔案
		if (StringUtils.isNotBlank(brief)) {
			saveToFile(newProduct.getProductId(), brief, "brief");
		}
		if (StringUtils.isNotBlank(description)) {
			saveToFile(newProduct.getProductId(), description, "description");
		}
		if (StringUtils.isNotBlank(details)) {
			saveToFile(newProduct.getProductId(), details, "details");
		}
		if (StringUtils.isNotBlank(orderNotice)) {
			saveToFile(newProduct.getProductId(), orderNotice, "orderNotice");
		}

		// 储存productcategory
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("productId", copyProductId);
		List<ProductCategory> productCategories = productcategoryDao.getList(criteria, null);
		ProductCategory newProductCategory = null;
		for (ProductCategory productCategory : productCategories) {
			newProductCategory = new ProductCategory();
			BeanUtils.copyProperties(newProductCategory, productCategory);
			newProductCategory.setProductId(newProduct.getProductId());
			getProductcategoryDao().saveOrUpdate(newProductCategory);
		}
		// 商品同步
		if (isVaildSync(newProduct)) {
			batchJobService.save("ProductSyncUpdateJob", toXML(newProduct), null, newProduct.getProductId());
		}
		return newProduct;
	}

	@Transactional(readOnly = false)
	public void delBrand(Brand brand) throws CoreException {
		brandDao.delete(brand);
	}

	@Transactional(readOnly = false)
	public boolean delProdCat(String[] delProductCategoryIds) {
		try {
			for (int i = 0; i < delProductCategoryIds.length; i++) {
				ProductCategory pc = (ProductCategory) baseManager.get(ProductCategory.class, Long
						.valueOf(delProductCategoryIds[i]));
				baseManager.delete(pc);
				Object[] result = baseManager.queryByHql("from ProdCatSE where categoryId=? and product.productId=?",
						new Object[] { pc.getCategoryId(), pc.getProductId() });
				if (result != null && result.length > 0) {
					for (Object obj : result) {
						ProdCatSE ps = (ProdCatSE) obj;
						baseManager.delete(ps);
					}
				}
				Object[] rcResult = baseManager.queryByHql("from ProdCatRC where categoryId=? and productId=?", new Object[] {
						String.valueOf(pc.getCategoryId()), pc.getProductId() });
				if (rcResult != null && rcResult.length > 0) {
					for (Object obj : rcResult) {
						ProdCatRC pr = (ProdCatRC) obj;
						baseManager.delete(pr);
					}
				}
			}
			return true;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Transactional(readOnly = false)
	public boolean publishProdCat(String categoryIdParam) {
		try {
			// ProdCatApply pa=(ProdCatApply)baseManager.get(ProdCatApply.class, Long.valueOf(categoryIdParam));
			// if(pa==null){
			// pa=new ProdCatApply();
			// pa.setCategoryId(Long.valueOf(categoryIdParam));
			// pa.setCreateDate(new Date());
			// pa.setCreateUser(AdminHelper.getUser().getUsername());
			// pa.setModifyDate(pa.getCreateDate());
			// pa.setModifyUser(pa.getCreateUser());
			// baseManager.save(pa);
			// }else{
			// pa.setModifyUser(AdminHelper.getUser().getUsername());
			// pa.setModifyDate(new Date());
			// baseManager.update(pa);
			// }
			// int count = getProductCategoryCountByCategoryId(Long.parseLong(categoryIdParam), null, null, false);
			//
			// Object[] allProduct = getProductCategoryByCategoryIdPager(Long.parseLong(categoryIdParam), null, null, 0,
			// count,
			// false);
			// for (int i = 0; i < allProduct.length; i++) {
			// Map map = (Map) allProduct[i];
			// String categoryId = (String) map.get("CATEGORY_ID");
			// String productId = (String) map.get("PRODUCT_ID");
			// String categoryPath = (String) map.get("CATEGORY_PATH");
			// ProdCatSE ps = null;
			// Object[] result = baseManager.queryByHql("from ProdCatSE where categoryId=? and product.productId=?",
			// new Object[] { categoryId, productId });
			// if (result != null && result.length > 0) {
			// ps = (ProdCatSE) result[0];
			//
			// }
			// if (ps == null) {
			// ps = new ProdCatSE();
			// ps.setSortWeight(400);
			//
			// }
			// ps.setCategoryId(Long.valueOf(categoryId));
			// ps.setCategoryPath(categoryPath);
			// Product p = (Product) baseManager.get(Product.class, productId);
			// ps.setProduct(p);
			//
			// ps.setSortOrder(400);
			// baseManager.saveOrUpdate(ps);
			// }

			Object[] result = baseManager.queryByHql(
					"from ProdCatSE where categoryId=? and sortWeight<? order by sortWeight asc", new Object[] {
							Long.valueOf(categoryIdParam), 400 });
			for (int i = 0; i < result.length; i++) {
				ProdCatSE ps = (ProdCatSE) result[i];
				ps.setSortOrder(i + 1);
				baseManager.update(ps);
			}
			baseManager.executeHql("delete from ProdCatSE where categoryId=? and sortWeight=?", new Object[] {
					Long.valueOf(categoryIdParam), 400 });
			baseManager.executeHql("update ProdCatSE set sortWeight=? where categoryId=?", new Object[] { 400,
					Long.valueOf(categoryIdParam) });
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	@Transactional(readOnly = false)
	public boolean deleteProductCategory(String[] id) throws CoreException {
		try {
			if (null != id) {
				for (String idstr : id) {
					getProductcategoryDao().deleteByPK(Long.parseLong(idstr));
				}
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	@Transactional(readOnly = false)
	public void delProductCategory(ProductCategory productCategory) throws CoreException {
		productcategoryDao.delete(productCategory);
	}

	@Transactional(readOnly = false)
	public void delProductPromotionFlag(ProductPromotionFlag productPromotionFlag) throws CoreException {
		productPromotionFlagDao.delete(productPromotionFlag);
	}

	@Transactional(readOnly = false)
	public void delVirtualProduct(VirtualProduct virtualProduct) throws CoreException {
		virtualproductDao.delete(virtualProduct);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.common.service.impl.DomainServiceImpl#get(java.io.Serializable)
	 */

	@Override
	public Product get(Serializable oid) throws CoreException {
		Product product = super.get(oid);
		if (null != product) {
			if (null != product.getSuppliers()) {
				Hibernate.initialize(product.getSuppliers());
			}
			// 分線維護權限檢核
			User user = AdminHelper.getUser();
			if (null != user) {
				// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
				if (user.getPermissions(Type.CATEGORY).size() > 0) {
					if (null == product.getCategory()) {
						product.setCategory(categoryService.get(Long.parseLong(String.valueOf(product.getMainCategoryID()))));
					}
					if (StringUtils.isNotBlank(product.getCategory().getRootId())) {
						if (!user.getPermissions(Type.CATEGORY).keySet().contains("CATEGORY_" + product.getCategory().getRootId())) {
							product = null;
						}
					}
				}
			}
		}
		return product;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getAddOnProductByAddOnProductId(java.lang.String)
	 */

	public AddOnProduct getAddOnProduct(String mainProductId, String addOnProductId) throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("mainProductId", mainProductId);
		criteria.addEq("addOnProductId", addOnProductId);
		return addonproductDao.getSingle(criteria, null);
	}

	public AddOnProduct getAddOnProductById(Long addOnId) throws CoreException {
		return addonproductDao.get(addOnId);
	}

	/**
	 * @return the addonproductDao
	 */
	public AddOnProductDao getAddonproductDao() {
		return addonproductDao;
	}

	public List<AddOnProduct> getAddOnProductList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "product.category.categoryPath");
		if (sortOrder == null) {
			return addonproductDao.getListPageable(critInRlike, defaultSort, firstResult, maxResults);
		}
		return addonproductDao.getListPageable(critInRlike, sortOrder, firstResult, maxResults);
	}

	/** DAO SET&GET */

	public List<String> getAddOnProductList(String mainProductId, String addOnProductId, String status, int firstResult,
			int maxResults) throws CoreException {
		return addonproductDao.getAddOnProductList(mainProductId, addOnProductId, status, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getAddOnProducts(java.lang.String)
	 */

	public Map<String, AddOnProduct> getAddOnProducts(String mainProductId, boolean nmProduct) throws CoreException {
		Map<String, AddOnProduct> result = null;
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("mainProductId", mainProductId);
		criteria.addEq("isDelete", "N");
		if (!nmProduct) {
			Date now = DateUtil.getCurrentTime();
			criteria.addEq("isEnable", "Y");
			criteria.addLe("startDate", now);
			criteria.addGe("endDate", now);
			criteria.addNe("addOnPrice", BigDecimal.valueOf(-1));
		} else {
			criteria.addEq("addOnPrice", BigDecimal.valueOf(-1));
		}
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "product.category.categoryPath");
		result = addonproductDao.getMap("addOnProductId", critInRlike, null);
		return result;
	}

	public Brand getBrandByBrandId(String brandId) throws CoreException {
		return brandDao.get(brandId);
	}

	/**
	 * @return the brandDao
	 */
	public ObjectDao<Brand> getBrandDao() {
		return brandDao;
	}

	public List<Brand> getBrandList(int firstResult, int maxResults, CommonCriteria criteria, String[] sortOrder)
			throws CoreException {
		if (sortOrder == null) {
			return brandDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		}
		return brandDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	@SuppressWarnings("unchecked")
	public List<Brand> getBrandList(int firstResult, int maxResults, String nameParam, String statusParam) {
		Map<String, Serializable> attrs = new HashMap<String, Serializable>();
		if (StringUtils.isNotBlank(nameParam)) {
			attrs.put("brandEname", nameParam.toUpperCase() + "%");
		}
		if (StringUtils.isNotBlank(statusParam)) {
			attrs.put("brandStatus", statusParam);
			return getBrandDao().getNameQuery("Brand.getListStatusIgnoreCase", attrs, firstResult, maxResults);
		}
		return getBrandDao().getNameQuery("Brand.getListIgnoreCase", attrs, firstResult, maxResults);
	}

	public Number getBrandListSize(CommonCriteria criteria) {
		return getBrandDao().getListSize(criteria);
	}

	/**
	 * @return the categoryDao
	 */
	public ObjectDao<Category> getCategoryDao() {
		return categoryDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductCategory(java.lang.Long)
	 */

	public ProductCategory getProductCategory(Long id) throws CoreException {
		return getProductCategory(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductCategoryByCategoryId(java.lang.Long)
	 */

	public List<Object> getProductCategoryByCategoryId(Long categoryId, String isDelete) throws CoreException {
		List<String> isDeleteList = new ArrayList<String>();
		if (StringUtils.isNotBlank(isDelete)) {
			isDeleteList.add(isDelete);
		}
		return getProductCategoryByCategoryId(categoryId, isDeleteList);
	}

	private String getCountSql(boolean isCheckPrice, String isDeleteSql, String keywordSql) {
		String tableName = "EC_VIEW_CATEGORY_PRODUCT_ES";
		if (isCheckPrice) {
			tableName = "EC_VIEW_CATEGORY_PRODUCT";
		}
		String countSql = "select distinct count(*) from " + tableName + " a,(select * from "
				+ "(select cat2.product_id, cat2.category_id, cat2.show_seq as s1,"
				+ "cat1.show_seq as s2,rank()over(partition by cat2.product_id "
				+ "order by cat2.show_seq,cat1.show_seq ) as rank  " + "from ec_category_main cat1, ec_product_category cat2 "
				+ "where cat1.category_id = cat2.category_id  " + "and cat1.category_path = cat2.category_path "
				+ "and cat1.is_delete  = 'N'  " + "and (cat1.category_path like ? or cat1.category_id=?)"
				+ "order by cat2.product_id desc) " + "where rank =1) b " + "where a.product_id = b.product_id " + keywordSql
				+ "and " + "substr(a. v_uk,  (InStr(a.v_uk,'_')) +1 ) = b.category_id and "
				+ "(a.category_path like ? or a.category_id=?) " + isDeleteSql + "order by  a.show_Seq asc,a.product_id desc";
		return countSql;
	}

	private String getSql(boolean isCheckPrice, String orderSql, String isDeleteSql, String keywordSql) {
		String tableName = "EC_VIEW_CATEGORY_PRODUCT_ES";
		if (isCheckPrice) {
			tableName = "EC_VIEW_CATEGORY_PRODUCT";
		}
		String sql = "SELECT * FROM(SELECT RESUL.* ,ROWNUM NUM FROM(" + "SELECT RESU.* from ("
				+ "SELECT RES.*, cs.sort_weight,cs.sort_order FROM (" + "select distinct a.* from "
				+ tableName
				+ " a,(select * from "
				+ "(select cat2.product_id, cat2.category_id, cat2.show_seq as s1,"
				+ "cat1.show_seq as s2,rank()over(partition by cat2.product_id "
				+ "order by cat2.show_seq,cat1.show_seq ) as rank  "
				+ "from ec_category_main cat1, ec_product_category cat2 "
				+ "where cat1.category_id = cat2.category_id  "
				+ "and cat1.category_path = cat2.category_path "
				+ "and cat1.is_delete  = 'N'  "
				+ "and (cat1.category_path like ? or cat1.category_id=?) "
				+ "order by cat2.product_id desc) "
				+ "where rank =1) b "
				+ "where a.product_id = b.product_id "
				+ keywordSql
				+ "and "
				+ "substr(a. v_uk,  (InStr(a.v_uk,'_')) +1 ) = b.category_id and "
				+ "(a.category_path like ? or a.category_id=?) "
				+ isDeleteSql

				+ ") RES "
				+ "LEFT JOIN EC_PROD_CAT_SE cs "
				+ "ON cs.prod_cat_id=RES.prodcut_category_id and cs.category_id=? and cs.product_id=RES.product_id "
				+ ") RESU " + orderSql + " ) RESUL " + " WHERE ROWNUM<=? " + ") " + "WHERE NUM>?";
		return sql;
	}

	public int getProductCategoryCountByCategoryId(Long categoryId, List<String> isDelete, String keyword,
			boolean isCheckPrice) {
		Category category = (Category) baseManager.get(Category.class, categoryId);

		if (category == null) {
			return 0;
		}
		String tempZ = "";
		if (Integer.valueOf(category.getLevel()) == 0) {
			tempZ = categoryId + "/%";
		} else if (category.getIsEndnode().equals("Y")) {
			tempZ = "%/" + categoryId;
		} else {
			tempZ = "%" + categoryId + "%";
		}
		String isDeleteSql = "";
		if (isDelete != null && isDelete.size() > 0) {
			String isDeleteStr = "";
			for (int i = 0; i < isDelete.size(); i++) {
				if (i > 0) {
					isDeleteStr += ",";
				}
				isDeleteStr += "'" + isDelete.get(i) + "'";
			}
			isDeleteSql = "and (a.is_delete in (" + isDeleteStr + ")) ";
		}
		String keywordSql = "";
		if (keyword != null) {
			keywordSql = "and (a.product_id like ? or a.product_name like ? or a.product_brief like ?) ";
		}
		int count = 0;
		if (keyword != null) {
			String keywordStr = "%" + keyword + "%";
			count = t.queryForInt(getCountSql(isCheckPrice, isDeleteSql, keywordSql), tempZ, categoryId, keywordStr,
					keywordStr, keywordStr, tempZ, categoryId);
		} else {
			count = t.queryForInt(getCountSql(isCheckPrice, isDeleteSql, keywordSql), tempZ, categoryId, tempZ, categoryId);
		}
		return count;
	}

	public Object[] getProductCategoryByCategoryIdPager(Long categoryId, List<String> isDelete, String keyword,
			Integer startAt, Integer maxRow, boolean isCheckPrice) throws CoreException {
		Category category = (Category) baseManager.get(Category.class, categoryId);

		if (category == null) {
			return null;
		}
		String tempZ = "";
		if (Integer.valueOf(category.getLevel()) == 0) {
			tempZ = categoryId + "/%";
		} else if (category.getIsEndnode().equals("Y")) {
			tempZ = "%/" + categoryId;
		} else {
			tempZ = "%" + categoryId + "%";
		}
		String isDeleteSql = "";
		if (isDelete != null && isDelete.size() > 0) {
			String isDeleteStr = "";
			for (int i = 0; i < isDelete.size(); i++) {
				if (i > 0) {
					isDeleteStr += ",";
				}
				isDeleteStr += "'" + isDelete.get(i) + "'";
			}
			isDeleteSql = "and (a.is_delete in (" + isDeleteStr + ")) ";
		}
		String keywordSql = "";
		if (keyword != null) {
			keywordSql = "and (a.product_id like ? or a.product_name like ? or a.product_brief like ?) ";
		}
		Object[] result = null;
		if (keyword != null) {
			String keywordStr = "%" + keyword + "%";
			result = baseManager.queryBySql(getSql(isCheckPrice, "order by  RESU.sort_weight asc, RESU.sort_order asc",
					isDeleteSql, keywordSql), new Object[] { tempZ, categoryId, keywordStr, keywordStr, keywordStr, tempZ,
					categoryId, categoryId, maxRow, startAt });
		} else {
			result = baseManager.queryBySql(getSql(isCheckPrice, "order by  RESU.sort_weight asc, RESU.sort_order asc",
					isDeleteSql, keywordSql), new Object[] { tempZ, categoryId, tempZ, categoryId, categoryId, maxRow, startAt });
		}
		return result;
	}

	public List<Object> getProductCategoryByCategoryId(Long categoryId, List<String> isDelete) throws CoreException {
		StringBuffer sb = new StringBuffer();
		List attrs = new ArrayList();
		sb.append("select c.id,c.productId,c.showSeq,p.productName,p.mainCategoryID from ProductCategory c,Product p ");
		sb.append("where c.productId = p.productId and c.categoryId = ? ");
		attrs.add(categoryId);
		if (null != isDelete && isDelete.size() > 0) {
			sb.append("and p.isDelete in ( ");

			for (int i = 0; i < isDelete.size(); i++) {
				if (i == 0) {
					sb.append("?");
				} else {
					sb.append(", ?");
				}
				attrs.add(isDelete.get(i));
			}
			sb.append(" )");
		}
		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分线维护权限检核
		sb.append("order by c.showSeq asc,c.productId desc ");
		List<Object> lists = getDao().getQueryByList(sb.toString(), attrs, 0, -1);
		return lists;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductCategoryByProduct(java.lang.String)
	 */

	public Map<String, ProductCategory> getProductCategoryByProduct(String productId) throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("productId", productId);
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");
		return productcategoryDao.getMap("categoryId", critInRlike, new String[] { "categoryPath" });
	}

	/**
	 * @return the productcategoryDao
	 */
	public ObjectDao<ProductCategory> getProductcategoryDao() {
		return productcategoryDao;
	}

	public List<ProductCategory> getProductCategoryList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		// 分身维护不判断权限criteria
		List<ProductCategory> productCategories = null;
		// CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");
		if (null == sortOrder) {
			productCategories = productcategoryDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		} else {
			productCategories = productcategoryDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
		}
		return productCategories;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductIds(int, int,
	 * com.yaodian100.core.common.dao.impl.CommonCriteria, java.lang.String[])
	 */

	public List getProductIds(int firstResult, int maxResults, CommonCriteria criteria, String[] sortOrder)
			throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "category.categoryPath");
		return getDao()
				.getAttributesPageable(new String[] { "productId" }, critInRlike, sortOrder, firstResult, maxResults);
	}

	public List<Product> getProductOnShelfPageableList(String prodId, String prodName, String prodType, String prodAttr,
			String supplierId, String categoryPath, String productBrand, int firstResult, int maxResults)
			throws CoreException {
		Map<String, Object> attrs = new HashMap<String, Object>();
		StringBuilder sb = new StringBuilder("");
		sb.append("select p from Product p ,Shelf s ");
		sb.append("where p.productType != '6' ");
		sb.append("and s.productId = p.productId ");
		sb.append("and s.shelfStatus = 'SHF500' ");

		if (StringUtils.isNotBlank(prodId)) {
			String[] temps = StringUtils.split(prodId, ",");
			StringBuffer tempStr = new StringBuffer("");
			for (String temp : temps) {
				tempStr.append("'").append(temp).append("'").append(",");
			}
			sb.append("and p.productId in ( ").append(tempStr.substring(0, tempStr.length() - 1)).append(" )");
		}

		if (StringUtils.isNotBlank(prodName)) {
			sb.append("and p.productName like :prodName ");
			attrs.put("prodName", prodName + "%");
		}
		if (StringUtils.isNotBlank(prodAttr)) {
			sb.append("and p.isDelete = :prodAttr ");
			attrs.put("prodAttr", prodAttr);
		}

		if (StringUtils.isNotBlank(prodType)) {
			sb.append("and p.productType = :prodType ");
			attrs.put("prodType", Integer.parseInt(prodType));
		}

		if (StringUtils.isNotBlank(supplierId)) {
			sb.append("and p.supplierId = :supplierId ");
			attrs.put("supplierId", supplierId);
		}

		if (StringUtils.isNotBlank(categoryPath)) {
			sb.append("and p.category.categoryPath like :categoryPath ");
			attrs.put("categoryPath", categoryPath + "%");
		}

		if (StringUtils.isNotBlank(productBrand)) {
			sb.append("and p.productBrand = :productBrand ");
			attrs.put("productBrand", productBrand);
		}
		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分線維護權限檢核
		sb.append("order by p.productId desc ");
		List<Product> products = getDao().getQueryByMap(sb.toString(), attrs, firstResult, maxResults);
		return products;
	}

	public Number getProductOnShelfPageableListSize(String prodId, String prodName, String prodType, String prodAttr,
			String supplierId, String categoryPath, String productBrand) throws CoreException {
		List<Product> queryResult = getProductOnShelfPageableList(prodId, prodName, prodType, prodAttr, supplierId,
				categoryPath, productBrand, 0, -1);
		return queryResult.size();
	}

	public ProductPromotionFlag getProductPromotionFlag(String productId) throws CoreException {
		return productPromotionFlagDao.get(productId);
	}

	public ObjectDao<ProductPromotionFlag> getProductPromotionFlagDao() {
		return productPromotionFlagDao;
	}

	public List<ProductPromotionFlag> getProductPromotionFlagList(int firstResult, int maxResults,
			CommonCriteria criteria, String[] sortOrder) throws CoreException {
		if (sortOrder == null) {
			return productPromotionFlagDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		}
		return productPromotionFlagDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	/**
	 * @return the proposeproductDao
	 */
	public ObjectDao<ProposeProduct> getProposeproductDao() {
		return proposeproductDao;
	}

	@Transactional(readOnly = false)
	public String getProposeProductIdNo() throws CoreException {
		String proposeProductId = "";
		ProposeProduct proposeproduct = new ProposeProduct();
		proposeProductId = proposeproductDao.save(proposeproduct).getId();
		proposeproductDao.delete(proposeproduct);
		return proposeProductId;
	}

	public ObjectDao<Shelf> getShelfDao() {
		return shelfDao;
	}

	public ShelfService getShelfService() {
		return shelfService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getSpecification(java.lang.Long)
	 */

	public Specification getSpecification(Long specId) throws CoreException {
		return specificationDao.get(specId);
	}

	/**
	 * @return the specificationDao
	 */
	public ObjectDao<Specification> getSpecificationDao() {
		return specificationDao;
	}

	public List<SpecificationInventory> getSpecificationInventory(CommonCriteria criteria) throws CoreException {
		return specificationinventoryDao.getList(criteria, null);
	}

	public SpecificationInventory getSpecificationInventory(String productId, Long specId) throws CoreException {
		SpecificationInventory result = null;
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("productId", productId);
		criteria.addEq("specId", specId);
		result = specificationinventoryDao.getSingle(criteria, null);
		return result;
	}

	/**
	 * @return the specificationinventoryDaoSum
	 * @throws CoreException
	 */
	public Map<String, String> getSpecificationinventoryDaoSum(List products) throws CoreException {
		return specificationinventoryDao.getSpecificationInventorySum(products);
	}

	public Map<String, SpecificationInventory> getSpecificationInventoryMap(String productId) throws CoreException {
		Map<String, SpecificationInventory> result = new HashMap<String, SpecificationInventory>();
		Object[] inventorys = baseManager
				.queryByHql(
						"select i from SpecificationInventory i,Specification s where i.specId = s.specificationId and s.isDelete = 'N' and s.productId = ? ",
						new Object[] { productId });
		if (null != inventorys && inventorys.length > 0) {
			SpecificationInventory specInventory = null;
			for (Object inventory : inventorys) {
				specInventory = (SpecificationInventory) inventory;
				result.put(specInventory.getSpecId().toString(), specInventory);
			}
		}
		return result;
	}

	public List<Specification> getSpecificationList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		if (sortOrder == null) {
			return specificationDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		}
		return specificationDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getSpecifications(java.lang.String)
	 */

	public Map<String, Specification> getSpecifications(String productId) throws CoreException {
		Map specMap = null;
		if (specificationCache != null) {
			try {
				specMap = specificationCache.get(productId);
			} catch (CacheException e) {
				CommonCriteria criteria = new CommonCriteria();
				criteria.addEq("productId", productId);
				criteria.addEq("isDelete", "N");
				specMap = specificationDao.getMap("specificationId", criteria, new String[] { "showSeq asc" });
				specificationCache.put(productId, specMap);
			}
		} else {
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("productId", productId);
			criteria.addEq("isDelete", "N");
			specMap = specificationDao.getMap("specificationId", criteria, new String[] { "showSeq asc" });
		}
		return specMap;
	}

	public int getStockOutByProductId(String productId) {
		Object[] obj = baseManager.queryByHql(
				"select count(productId) from ViewWishList where productId = ? and isRestockNotify = 'Y' "
						+ mergeHqlInRlike("categoryPath"), new Object[] { productId });
		return Integer.parseInt(obj[0].toString());
	}

	public List<Object> getStockOutReport(Long categoryId, String isDelete, String pmId, String productId,
			String productName, String supplier, boolean stockNotify, int startStockQty, int endStockQty)
			throws CoreException {
		StringBuffer sb = new StringBuffer();
		List<Object> attrs = new ArrayList<Object>();
		if (stockNotify) {
			sb.append("select * from ");
			sb.append("( select u.native_name,p.product_id ,p.product_name,p.arrival_date, ");
			sb.append("w.restock_date,count(w.product_id) stock_qty,sa.companyname,w.shelf_qty,p.main_category_id ");
			sb.append("from comm_admin_user u,ec_product_main p,ec_view_wish_list w,ec_category_main m,");
			sb.append("ec_supplier_apply sa ");
			sb.append("where u.user_name = p.pm_id ");
			sb.append("and p.supplier_id = sa.supplier_id ");
			sb.append("and m.category_id = p.main_category_id  ");
			sb.append("and w.product_id = p.product_id  ");
			sb.append("and w.shelf_qty = 0 ");
			sb.append("and w.is_restock_notify = 'Y' ");
			sb.append("and p.is_delete <> 'Y' ");
		} else {
			sb.append("select distinct u.native_name,a.product_id ,p.product_name,a.spec_id,d.specification_name, ");
			sb.append("a.available_inventory,a.sold_inventory,a.cancel_inventory,p.is_delete ,p.main_category_id, ");
			sb.append("d.spec_status ");
			sb
					.append("from comm_admin_user u,ec_specification_inventory a,ec_product_main p,ec_specification d,ec_category_main m ");
			sb.append("where ");
			sb.append("u.user_name = p.pm_id ");
			sb.append("and m.category_id = p.main_category_id  ");
			sb.append("and p.is_delete <> 'Y' ");
			sb.append("and a.spec_id = d.specification_id ");
			sb.append("and a.product_id = p.product_id  ");
			sb.append("and a.available_inventory > 0  ");
			sb.append("and (a.available_inventory-a.sold_inventory+a.cancel_inventory)=0 ");
		}
		sb.append(mergeHqlInRlike("m.category_path"));// 分線維護權限檢核
		if (categoryId != 0) {
			sb.append("and p.main_category_id=?  ");
			attrs.add(categoryId);
		}
		if (StringUtils.isNotBlank(isDelete)) {
			sb.append("and p.is_delete=?  ");
			attrs.add(isDelete);
		}
		if (StringUtils.isNotBlank(pmId)) {
			sb.append("and p.pm_id=?  ");
			attrs.add(pmId);
		}
		if (StringUtils.isNotBlank(productId)) {
			StringBuffer tempStr = new StringBuffer("");
			String[] temps = StringUtils.split(productId, ",");
			for (String temp : temps) {
				tempStr.append("'").append(temp).append("'").append(",");
			}
			sb.append("and p.product_id in ( ").append(tempStr.substring(0, tempStr.length() - 1)).append(" )");
		}
		if (StringUtils.isNotBlank(productName)) {
			sb.append("and p.product_name like ? ");
			attrs.add("%" + productName + "%");
		}
		if (StringUtils.isNotBlank(supplier)) {
			sb.append("and p.supplier_id =?  ");
			attrs.add(supplier);
		}
		if (stockNotify) {
			sb.append("group by ");
			sb.append("u.native_name, p.product_id, p.product_name,p.arrival_date,w.restock_date,sa.companyname,");
			sb.append("w.shelf_qty,p.main_category_id ) aaa ");
			sb.append("left join  ");
			sb.append("(select category_id,sys_connect_by_path(category_name||'('||category_id||')', ',') as path ");
			sb.append("from ec_category_main ");
			sb.append("start with parent_id=0 ");
			sb.append("connect by prior category_id=parent_id) bbb ");
			sb.append("on aaa.main_category_id=bbb.category_id ");
			sb.append("where 1 = 1 ");
			if (startStockQty > 0 && endStockQty > 0) {
				sb.append("and stock_qty between ? and ? ");
				attrs.add(startStockQty);
				attrs.add(endStockQty);
			}
			if (startStockQty > 0 && endStockQty == 0) {
				sb.append("and stock_qty >= ? ");
				attrs.add(startStockQty);
			}
			if (startStockQty == 0 && endStockQty > 0) {
				sb.append("and stock_qty <= ? ");
				attrs.add(endStockQty);
			}
		}
		List<Object> lists = getDao().getSQLQueryByList(sb.toString(), attrs, 0, -1);
		return lists;
	}

	/**
	 * @return the supplierApplyDao
	 */
	public ObjectDao<SupplierApply> getSupplierApplyDao() {
		return supplierApplyDao;
	}

	public List<SupplierApply> getSupplierApplyList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		if (sortOrder == null) {
			return supplierApplyDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		}
		return supplierApplyDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	public ObjectDao<ViewPickProduct> getViewPickProductDao() {
		return viewPickProductDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getViewNPICKMList(int, int,
	 * com.yaodian100.core.common.dao.impl.CommonCriteria, java.lang.String[])
	 */

	public List<ViewPickProduct> getViewPickProductList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");
		return viewPickProductDao.getListPageable(critInRlike, sortOrder, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.product.service.ProductService#getgetViewNPICKMListSize(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */

	public Number getViewPickProductListSize(CommonCriteria criteria) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");
		return viewPickProductDao.getListSize(critInRlike);
	}

	/**
	 * @return the virtualproductDao
	 */
	public ObjectDao<VirtualProduct> getVirtualproductDao() {
		return virtualproductDao;
	}

	public List<VirtualProduct> getVirtualProductList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		if (sortOrder == null) {
			return virtualproductDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
		}
		return virtualproductDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	boolean isVaildSync(Product product) {
		boolean isSync = false;
		if (product.getProductType() == 6) {// n选m商品不用同步
			return false;
		} else {
			String beanParm = toXML(product);
			List<Specification> specs = product.getSpecifications();
			if (!StringUtils.isBlank(beanParm) && !StringUtils.isBlank(product.getSupplierId()) && specs.size() > 0) {
				isSync = true;
			}
			return isSync;
		}
	}

	// 直接購買

	public ArrayList<String> orderBuyNowInfo(String[] itemNo, String[] specNo, String[] qty, String[] categoryPath,
			String[] type, String presents, String addOns) throws CoreException {
		ArrayList<String> buyNowList = new ArrayList();
		StringBuilder sb = new StringBuilder();

		if (StringUtils.isNotBlank(itemNo[0])) {
			sb.setLength(0);
			Product product = this.get(itemNo[0]);
			String tmpPdName = product.getProductName();
			tmpPdName = tmpPdName.replace(",", "，");
			tmpPdName = tmpPdName.replace("\"", "“");
			sb.append(tmpPdName).append(",");
			// sb.append(product.getProductName().replace(",", "，")).append(",");
			sb.append(type[0]).append(",");
			Specification spec = specificationDao.get(Long.parseLong(specNo[0]));
			sb.append(spec.getSpecificationName()).append(",");
			Shelf shelf = shelfService.getActiveShelfByProductId(itemNo[0]);
			sb.append(shelf.getShelfPrice()).append(",");
			sb.append(qty[0]).append(",");
			sb.append(shelf.getShelfPrice().multiply(new BigDecimal(qty[0]))).append(",");
			sb.append(itemNo[0]).append(",");
			sb.append(categoryPath[0]).append(",");
			sb.append(specNo[0]);
			buyNowList.add(sb.toString());
		}

		// 贈品
		if (!presents.equals("null")) {
			JSONArray jsonObject = JSONArray.fromObject(presents);
			for (int i = 0; i < jsonObject.size(); i++) {
				JSONObject jsonObject2 = (JSONObject) jsonObject.get(i);
				if (StringUtils.isNotBlank(jsonObject2.get("itemNo").toString())) {
					sb.setLength(0);
					Product product = this.get(jsonObject2.get("itemNo").toString());
					String tmpPdName = product.getProductName();
					tmpPdName = tmpPdName.replace(",", "，");
					tmpPdName = tmpPdName.replace("\"", "“");
					sb.append(tmpPdName).append(",");
					// sb.append(product.getProductName().replace(",", "，")).append(",");
					sb.append(jsonObject2.get("type").toString()).append(",");
					Specification spec = specificationDao.get(Long.parseLong(jsonObject2.get("specNo").toString()));
					sb.append(spec.getSpecificationName()).append(",");
					sb.append("0.00").append(",");
					sb.append(jsonObject2.get("qty").toString()).append(",");
					sb.append("0.00").append(",");
					sb.append(jsonObject2.get("itemNo").toString()).append(",");
					sb.append(jsonObject2.get("categoryPath").toString()).append(",");
					sb.append(jsonObject2.get("specNo").toString());
					buyNowList.add(sb.toString());
				}
			}
		}

		// 加購
		if (!addOns.equals("null")) {
			JSONArray jsonObject = JSONArray.fromObject(addOns);
			for (int i = 0; i < jsonObject.size(); i++) {
				JSONObject jsonObject2 = (JSONObject) jsonObject.get(i);
				if (StringUtils.isNotBlank(jsonObject2.get("itemNo").toString())) {
					sb.setLength(0);
					Product product = this.get(jsonObject2.get("itemNo").toString());
					String tmpPdName = product.getProductName();
					tmpPdName = tmpPdName.replace(",", "，");
					tmpPdName = tmpPdName.replace("\"", "“");
					sb.append(tmpPdName).append(",");
					// sb.append(product.getProductName().replace(",", "，")).append(",");
					sb.append(jsonObject2.get("type").toString()).append(",");
					Specification spec = specificationDao.get(Long.parseLong(jsonObject2.get("specNo").toString()));
					sb.append(spec.getSpecificationName()).append(",");
					if (jsonObject2.get("type").toString().equals("3")) {// 加購
						CommonCriteria crit = new CommonCriteria();
						crit.addEq("mainProductId", itemNo[0]);
						crit.addEq("addOnProductId", jsonObject2.get("itemNo").toString());
						crit.addEq("isEnable", "Y");
						crit.addEq("isDelete", "N");
						AddOnProduct addOnProduct = addonproductDao.getSingle(crit, null);
						if (null != addOnProduct) {
							sb.append(addOnProduct.getAddOnPrice()).append(",");
							sb.append(jsonObject2.get("qty").toString()).append(",");
							sb.append(addOnProduct.getAddOnPrice().multiply(new BigDecimal(jsonObject2.get("qty").toString())))
									.append(",");
							sb.append(jsonObject2.get("itemNo").toString()).append(",");
							sb.append(jsonObject2.get("categoryPath").toString()).append(",");
							sb.append(jsonObject2.get("specNo").toString());
							buyNowList.add(sb.toString());
						}
					}
					if (jsonObject2.get("type").toString().equals("6")) {// N選M
						sb.append("0.00").append(",");
						sb.append(jsonObject2.get("qty").toString()).append(",");
						sb.append("0.00").append(",");
						sb.append(jsonObject2.get("itemNo").toString()).append(",");
						sb.append(jsonObject2.get("categoryPath").toString()).append(",");
						sb.append(jsonObject2.get("specNo").toString());
						buyNowList.add(sb.toString());
					}
				}
			}
		}
		return buyNowList;
	}

	public String readBrandFromFile(String brandId) throws CoreException {
		StringBuffer context = new StringBuffer();
		try {
			String filename = ServerValue.getFrontApachePath() + File.separator + "static" + File.separator + File.separator
					+ "brand" + File.separator;
			File aFile = new File(filename + File.separator + brandId + File.separator + brandId + ".txt");
			if (aFile.isFile()) {
				FileReader fr = new FileReader(aFile);
				int ch;
				do {
					ch = fr.read();
					if (ch != -1) {
						context.append((char) ch);
					}
				} while (ch != -1);
				fr.close();
			}
		} catch (IOException e) {
			logger.info("ProductAction_readBrandFromFile error :{}", e.toString());
		}
		return context.toString();
	}

	/** 將brief,description,details,orderNotice 檔案讀出 */
	public String readFromFile(String productId, String contextType) throws CoreException {
		StringBuffer context = new StringBuffer();
		try {
			File aFile = new File(ServerValue.getMidProdHtmlPath() + File.separator + productId.substring(0, 4)
					+ File.separator + productId + File.separator + productId + "_" + contextType + ".txt");
			if (aFile.isFile()) {
				FileReader fr = new FileReader(aFile);
				int ch;
				do {
					ch = fr.read();
					if (ch != -1) {
						context.append((char) ch);
					}
				} while (ch != -1);
				fr.close();
			}
		} catch (IOException e) {
			logger.info("ProductAction_saveToFile error :{}", e.toString());
		}
		return context.toString();
	}

	public String readOrderNotice(String categoryId) throws CoreException {
		StringBuffer context = new StringBuffer();
		try {
			File aFile = new File(ServerValue.getMidProdHtmlPath() + categoryId + ".txt");
			context.append(FileUtils.readFileToString(aFile));
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return context.toString();
	}

	@Override
	@Transactional(readOnly = false)
	public Product save(Product entity) throws CoreException {
		Product resutlt = super.save(entity);
		logService.save(getClass().getSimpleName(), "save", resutlt);
		// 商品同步
		if (isVaildSync(resutlt)) {
			batchJobService.save("ProductSyncUpdateJob", toXML(resutlt), null, resutlt.getProductId());
		}

		return resutlt;
	}

	// 
	// public SpecificationInventory getOneSpecificationInventory(CommonCriteria criteria) throws CoreException {
	//
	// return specificationinventoryDao.getList(criteria, null).get(0);
	// }

	@Transactional(readOnly = false)
	public void saveAddOnProduct(AddOnProduct addOnProduct) throws CoreException {
		addonproductDao.saveOrUpdate(addOnProduct);
	}

	@Transactional(readOnly = false)
	public Brand saveBrand(Brand brand) throws CoreException {
		return brandDao.saveOrUpdate(brand);
	}

	/**
	 * 將品牌故事 儲存成檔案
	 * 
	 * @return
	 */
	public void saveBrandToFile(String brandId, String context) {
		try {
			String filename = ServerValue.getFrontApachePath() + File.separator + "static" + File.separator + File.separator
					+ "brand" + File.separator;
			FileUtils.forceMkdir(new File(filename + File.separator + brandId + File.separator));
			File file = new File(filename + File.separator + brandId + File.separator + brandId + ".txt");
			FileUtils.writeStringToFile(file, context);
		} catch (IOException e) {
			logger.info("ProductAction_saveBrandToFile error :{}", e.toString());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#saveOrUpdateAddOnProductBatch(java.util.List)
	 */

	@Transactional(readOnly = false)
	public boolean saveOrUpdateAddOnProductBatch(List<AddOnProduct> addOnProducts, List<AddOnProduct> removeProducts)
			throws CoreException {
		try {
			// 移除旧资料
			if (!removeProducts.isEmpty()) {
				getAddonproductDao().deleteBatch(removeProducts);
			}
			boolean result = false;
			List<AddOnProduct> removeAddProduct = new ArrayList<AddOnProduct>();
			for (AddOnProduct aop : addOnProducts) {
				// 判斷是否有不屬於該權限的資料
				if (null == aop.getAddProduct()) {
					result = true;
				}
				if (result) {
					removeAddProduct.add(aop);
				}
			}
			if (!removeAddProduct.isEmpty()) {
				// 移除不屬於該權限的資料
				getAddonproductDao().deleteBatch(removeAddProduct);
				addOnProducts.removeAll(removeAddProduct);
			}

			getAddonproductDao().saveOrUpdateBatch(addOnProducts);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#saveOrUpdateProduct(com.yaodian100.ec.product.entity.Product)
	 */

	@Transactional(readOnly = false)
	public Product saveOrUpdateProduct(Product product, ProductPromotionFlag productPromotionFlag) throws CoreException {
		Product newProduct = null;
		try {
			if (null == product.getProductId()) {
				product.setProductId(getProposeProductIdNo());
			}
			String orderNotice = product.getProductOrderNotice();
			String description = product.getProductDescription();
			String brief = product.getProductBrief();
			String details = product.getProductDetails();
			String scmNotice = product.getScmNotice();

			// // 将特色去除html code存入db
			if (StringUtils.isNotBlank(brief)) {
				product.setProductBrief(StringUtils.left(com.yaodian100.core.common.utils.StringUtils.removeHTML(brief, true),
						50));
			}
			// 将活动说明去除html code存入db
			if (StringUtils.isNotBlank(description)) {
				product.setProductDescription(StringUtils.left(com.yaodian100.core.common.utils.StringUtils.removeHTML(
						description, true), 50));
			}
			// 将活动规格内容去除html code存入db
			if (StringUtils.isNotBlank(details)) {
				product.setProductDetails(StringUtils.left(com.yaodian100.core.common.utils.StringUtils.removeHTML(details,
						true), 50));
			}
			product.setProductOrderNotice("");// 购物须知不须存到db
			if (StringUtils.isBlank(productPromotionFlag.getProductId())) {
				productPromotionFlag.setProductId(product.getProductId());
			}
			product.setProductPromotionFlag(productPromotionFlag);
			newProduct = getDao().saveOrUpdate(product);
			logService.save(getClass().getSimpleName(), "saveOrUpdateProduct", newProduct);
			// 储存成檔案
			if (StringUtils.isNotBlank(brief)) {
				saveToFile(newProduct.getProductId(), brief, "brief");
			}
			if (StringUtils.isNotBlank(description)) {
				saveToFile(newProduct.getProductId(), description, "description");
			}
			if (StringUtils.isNotBlank(details)) {
				saveToFile(newProduct.getProductId(), details, "details");
			}
			if (StringUtils.isNotBlank(orderNotice)) {
				saveToFile(newProduct.getProductId(), orderNotice, "orderNotice");
			}

			if ("Y".equals(newProduct.getIsScm())
					&& StringUtils.isNotBlank(scmNotice.replace("<br />", "").replace("<br/>", "").trim())) {
				saveToFile(newProduct.getProductId(), scmNotice, "scmNotice");
			} else {
				if ("Y".equals(newProduct.getIsScm())) {
					saveToFile(newProduct.getProductId(), "", "scmNotice");
				}
			}

			// 储存productcategory(删除旧的主目录)
			ProductCategory productCategory = null;
			int showSeq = 101;
			if (product.getOldMainCategoryID() != 0) {
				CommonCriteria criteria = new CommonCriteria();
				criteria.addEq("productId", newProduct.getProductId());
				criteria.addEq("categoryId", Long.parseLong(String.valueOf(product.getOldMainCategoryID())));
				productCategory = productcategoryDao.getSingle(criteria, null);
				if (null != productCategory) {
					showSeq = productCategory.getShowSeq();
					productcategoryDao.delete(productCategory);
				}
			}

			// 查詢productCategory內是否已經有商品主目錄資料
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("productId", newProduct.getProductId());
			criteria.addEq("categoryId", Long.parseLong(String.valueOf(newProduct.getMainCategoryID())));
			productCategory = productcategoryDao.getSingle(criteria, null);
			if (null == productCategory) {
				// 新增新的主目录
				productCategory = new ProductCategory();
				productCategory.setProductId(newProduct.getProductId());
				Category category = getCategoryDao().get(Long.parseLong(String.valueOf(newProduct.getMainCategoryID())));
				productCategory.setCategoryName(category.getName());
				productCategory.setCategoryPath(category.getCategoryPath());
				productCategory.setCategoryId(Long.parseLong(String.valueOf(newProduct.getMainCategoryID())));
				productCategory.setShowSeq(showSeq);
				getProductcategoryDao().saveOrUpdate(productCategory);
			}

			// 商品同步
			if (isVaildSync(newProduct)) {
				batchJobService.save("ProductSyncUpdateJob", toXML(newProduct), null, newProduct.getProductId());
			}

			// 若商品销售状态为y或q时，要将n选m次商品移除&搭售的商品的启用状态设为关闭
			if (StringUtils.equalsIgnoreCase("Y", product.getIsDelete())
					|| StringUtils.equalsIgnoreCase("Q", product.getIsDelete())) {
				// 搭售商品金额大于等于0(加购、赠品)
				baseManager.executeHql("update AddOnProduct set isEnable = 'N' where addOnProductId = ? and addOnPrice >= 0 ",
						new Object[] { product.getProductId() });
				// 移除n选m商品
				baseManager.executeHql("delete from AddOnProduct where addOnProductId = ? and addOnPrice = -1",
						new Object[] { product.getProductId() });
			}
		} catch (Exception e) {
			logger.info("error:{}", e.fillInStackTrace());
		}
		return newProduct;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#saveProduct(com.yaodian100.ec.product.entity.Product,
	 * com.yaodian100.ec.product.entity.ProductPromotionFlag)
	 */

	@Transactional(readOnly = false)
	public Product saveOrUpdateProductByPickProduct(Product product, ProductPromotionFlag productPromotionFlag,
			Shelf shelf) throws CoreException, IllegalAccessException, InvocationTargetException {
		String orderNotice = product.getProductOrderNotice();
		String description = product.getProductDescription();
		String brief = product.getProductBrief();
		String details = product.getProductDetails();
		String scmNotice = product.getScmNotice();

		if (StringUtils.isBlank(product.getProductId())) {
			product.setProductId(getProposeProductIdNo());
		}

		// 将特色去除html code存入db
		if (StringUtils.isNotBlank(brief)) {
			product.setProductBrief(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils
					.removeHTML(brief, true), 0, 50));
		}
		// 将活动说明去除html code存入db
		if (StringUtils.isNotBlank(description)) {
			product.setProductDescription(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(
					description, true), 0, 50));
		}
		// 将活动规格内容去除html code存入db
		if (StringUtils.isNotBlank(details)) {
			product.setProductDetails(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(details,
					true), 0, 50));
		}
		product.setProductOrderNotice("");// 购物须知不须存到db
		// if (StringUtils.isNotBlank(orderNotice))// 将购物须知去除html code存入db
		// product.setProductOrderNotice(StringUtils.substring(com.yaodian100.core.common.utils.StringUtils.removeHTML(
		// orderNotice, true), 48));

		if (StringUtils.isBlank(productPromotionFlag.getProductId())) {
			productPromotionFlag.setProductId(product.getProductId());
		}
		product.setProductPromotionFlag(productPromotionFlag);
		// 檢核供應商資料(若供應商設為非轉單，則同時異動商品為非轉單商品
		SupplierApply supplierApply = supplierApplyDao.get(product.getSupplierId());
		if (supplierApply.getIsScm().equals("N")) {
			product.setIsScm(supplierApply.getIsScm());
		}
		Product tempProduct = getDao().saveOrUpdate(product);
		logService.save(getClass().getSimpleName(), "saveOrUpdateProductByPickProduct", tempProduct);
		// 储存成檔案
		if (StringUtils.isNotBlank(brief)) {
			saveToFile(tempProduct.getProductId(), brief, "brief");
		}
		if (StringUtils.isNotBlank(description)) {
			saveToFile(tempProduct.getProductId(), description, "description");
		}
		if (StringUtils.isNotBlank(details)) {
			saveToFile(tempProduct.getProductId(), details, "details");
		}
		if (StringUtils.isNotBlank(orderNotice)) {
			saveToFile(tempProduct.getProductId(), orderNotice, "orderNotice");
		}
		if ("Y".equals(tempProduct.getIsScm()) && StringUtils.isNotBlank(scmNotice)) {
			saveToFile(tempProduct.getProductId(), scmNotice.replace("<br />", "").replace("<br/>", "").trim(), "scmNotice");
		} else {
			saveToFile(tempProduct.getProductId(), "", "scmNotice");
		}
		// 储存spec
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("productId", tempProduct.getProductId());
		List<Specification> specList = getSpecificationDao().getList(criteria, null);
		if (specList.size() == 0) {
			Specification spec = new Specification();
			spec.setProductId(tempProduct.getProductId());
			spec.setIsDelete("N");
			spec.setMaxCountPerOrder(-1);
			spec.setMaxCountPerOrder(-1);
			spec.setReverseInventory(-1);
			spec.setSafeInventory(-1);
			spec.setSpecificationName("N选M");
			spec.setShowSeq(1);
			getSpecificationDao().saveOrUpdate(spec);
		}
		// 储存productcategory(删除旧的主目录)
		ProductCategory productCategory = null;
		int showSeq = 101;
		if (product.getOldMainCategoryID() != 0) {
			criteria = new CommonCriteria();
			criteria.addEq("productId", product.getProductId());
			criteria.addEq("categoryId", Long.parseLong(String.valueOf(product.getOldMainCategoryID())));
			productCategory = productcategoryDao.getSingle(criteria, null);

			if (null != productCategory) {
				showSeq = productCategory.getShowSeq();
				productcategoryDao.delete(productCategory);
			}
		}

		// 查詢productCategory內是否已經有商品主目錄資料
		criteria = new CommonCriteria();
		criteria.addEq("productId", product.getProductId());
		criteria.addEq("categoryId", Long.parseLong(String.valueOf(product.getMainCategoryID())));
		productCategory = productcategoryDao.getSingle(criteria, null);
		if (null == productCategory) {
			productCategory = new ProductCategory();
			Category category = getCategoryDao().get(Long.parseLong(String.valueOf(tempProduct.getMainCategoryID())));
			productCategory.setProductId(tempProduct.getProductId());
			productCategory.setCategoryName(category.getName());
			productCategory.setCategoryPath(category.getCategoryPath());
			productCategory.setCategoryId(Long.parseLong(String.valueOf(tempProduct.getMainCategoryID())));
			productCategory.setShowSeq(showSeq);
			getProductcategoryDao().save(productCategory);
		}
		// 新增上架檔
		if (StringUtils.isBlank(shelf.getProductId())) {
			shelf.setProductId(tempProduct.getProductId());
		}

		getShelfDao().saveOrUpdate(shelf);
		return tempProduct;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#saveOrUpdateProductCategoryBatch(java.util.List)
	 */

	@Transactional(readOnly = false)
	public boolean saveOrUpdateProductCategoryBatch(Product product, List<ProductCategory> productCategories)
			throws CoreException {
		try {
			// 更新主目录资料
			update(product);
			// 删除原本的资料
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("productId", product.getProductId());
			List<ProductCategory> objects = getProductcategoryDao().getList(criteria, null);
			getProductcategoryDao().deleteBatch(objects);
			// 加入更新的资料
			getProductcategoryDao().saveOrUpdateBatch(productCategories);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	@Transactional(readOnly = false)
	public boolean saveOrUpdateMainProductCategoryBatch(List<Product> products, String oldCateId, String newCateId,
			boolean delOldCateId) throws CoreException {
		try {
			Category newCategory = categoryDao.get(Long.parseLong(newCateId));
			ProductCategory newProdCate = null;
			// 删除原本的资料
			if (delOldCateId) {
				baseManager.executeHql("delete ProductCategory where  categoryId ='" + oldCateId + "' ", new Object[] {});
			}
			for (Product product : products) {
				// 加入更新的资料
				Object[] objs = baseManager.queryByHql("from ProductCategory where categoryId = ? and productId = ? ",
						new Object[] { newCateId, product.getProductId() });
				// logger.info("xxx:{}", product.getProductId());
				if (ArrayUtils.isEmpty(objs)) {
					newProdCate = new ProductCategory();
					newProdCate.setCategoryId(newCategory.getId());
					newProdCate.setCategoryName(newCategory.getName());
					newProdCate.setCategoryPath(newCategory.getCategoryPath());
					newProdCate.setProductId(product.getProductId());
					newProdCate.setShowSeq(101);
					saveProductCategory(newProdCate);
					// logger.info("xxx2:{}", newCateId);
				}
				product.setMainCategoryID(newCategory.getId().intValue());
				// 更新主目录资料
				save(product);
			}
		} catch (Exception e) {
			logger.info("exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.product.service.ProductService#saveOrUpdateShelfByPickProduct(com.yaodian100.ec.shelf.entity.
	 * Shelf, com.yaodian100.ec.product.entity.Product)
	 */

	@Transactional(readOnly = false)
	public Shelf saveOrUpdateShelfByPickProduct(Shelf shelf, Product product) throws CoreException {
		try {
			shelf = getShelfDao().saveOrUpdate(shelf);
			getDao().saveOrUpdate(product);
			logService.save(getClass().getSimpleName(), "saveOrUpdateShelfByPickProduct", shelf);
		} catch (CoreException e) {
			throw new CoreException("新增/修改上架檔失败");
		}
		return shelf;
	}

	@Transactional(readOnly = false)
	public void saveProductCategory(ProductCategory productCategory) throws CoreException {
		productcategoryDao.saveOrUpdate(productCategory);

	}

	@Transactional(readOnly = false)
	public void saveProductPromotionFlag(ProductPromotionFlag productPromotionFlag) throws CoreException {
		productPromotionFlagDao.saveOrUpdate(productPromotionFlag);

	}

	@Transactional(readOnly = false)
	public void saveSpecification(Specification specification) throws CoreException {
		specification = specificationDao.saveOrUpdate(specification);
		// 商品同步，由spec反查prod
		Product product = getDao().get(specification.getProductId());
		// Hibernate.initialize(product.getSpecifications());
		if (isVaildSync(product)) {
			batchJobService.save("ProductSyncUpdateJob", toXML(product), null, product.getProductId());
		}

	}

	@Transactional(readOnly = false)
	public void saveSpecificationInventory(SpecificationInventory specificationInventory) throws CoreException {
		specificationinventoryDao.saveOrUpdate(specificationInventory);
	}

	@Transactional(readOnly = false)
	public void saveSpecificationInventoryAndInvalid(SpecificationInventory specificationInventory, String invHistoryId)
			throws CoreException {
		specificationinventoryDao.saveOrUpdate(specificationInventory);
		StringBuffer sql = new StringBuffer("insert into EC_SPEC_INVENTORY_VALID (VALID_ID) values (?) ");
		t.update(sql.toString(), new Object[] { invHistoryId });
	}

	/**
	 * 將brief,description,details 儲存成檔案
	 * 
	 * @return
	 */
	void saveToFile(String productId, String context, String contextType) {
		try {
			String filename = ServerValue.getMidProdHtmlPath();
			FileUtils.forceMkdir(new File(filename + File.separator + productId.substring(0, 4) + File.separator));
			FileUtils.forceMkdir(new File(filename + File.separator + productId.substring(0, 4) + File.separator + productId
					+ File.separator));
			File file = new File(filename + File.separator + productId.substring(0, 4) + File.separator + productId
					+ File.separator + productId + "_" + contextType + ".txt");
			context = StringUtils
					.remove(
							context,
							"<link href=\"http://www.yaodian100.com/css/yaodian100_pages_v2.css\" media=\"screen,print\" rel=\"stylesheet\" type=\"text/css\" />");
			context = StringUtils
					.remove(
							context,
							"<link href=\"http://www.yaodian100.com/css/pdpagese_v2.css\" media=\"screen,print\" rel=\"stylesheet\" type=\"text/css\" />");
			context = StringUtils.replace(context, "www.yaodian100.com/PImg", "s.yaodian100.com/PImg");
			FileUtils.writeStringToFile(file, context);
		} catch (IOException e) {
			logger.info("ProductAction_saveToFile error :{}", e.toString());
		}
	}

	@Transactional(readOnly = false)
	public void saveVirtualProduct(VirtualProduct virtualProduct) throws CoreException {
		virtualproductDao.saveOrUpdate(virtualProduct);
	}

	/**
	 * @param addonproductDao the addonproductDao to set
	 */
	public void setAddonproductDao(AddOnProductDao addonproductDao) {
		this.addonproductDao = addonproductDao;
	}

	/**
	 * @param brandDao the brandDao to set
	 */
	public void setBrandDao(ObjectDao<Brand> brandDao) {
		this.brandDao = brandDao;
	}

	/**
	 * @param categoryDao the categoryDao to set
	 */
	public void setCategoryDao(ObjectDao<Category> categoryDao) {
		this.categoryDao = categoryDao;
	}

	/**
	 * @param productcategoryDao the productcategoryDao to set
	 */
	public void setProductcategoryDao(ObjectDao<ProductCategory> productcategoryDao) {
		this.productcategoryDao = productcategoryDao;
	}

	public void setProductPromotionFlagDao(ObjectDao<ProductPromotionFlag> productPromotionFlagDao) {
		this.productPromotionFlagDao = productPromotionFlagDao;
	}

	/**
	 * @param proposeproductDao the proposeproductDao to set
	 */
	public void setProposeproductDao(ObjectDao<ProposeProduct> proposeproductDao) {
		this.proposeproductDao = proposeproductDao;
	}

	public void setShelfDao(ObjectDao<Shelf> shelfDao) {
		this.shelfDao = shelfDao;
	}

	public void setShelfService(ShelfService shelfService) {
		this.shelfService = shelfService;
	}

	/**
	 * @param specCache the specCache to set
	 */
	public void setSpecCache(CacheService<Map> specCache) {
		this.specCache = specCache;
	}

	/**
	 * @param specificationCache the specificationCache to set
	 */
	public void setSpecificationCache(CacheService<Map> specificationCache) {
		this.specificationCache = specificationCache;
	}

	/**
	 * @param specificationDao the specificationDao to set
	 */
	public void setSpecificationDao(ObjectDao<Specification> specificationDao) {
		this.specificationDao = specificationDao;
	}

	/**
	 * @param specificationinventoryDao the specificationinventoryDao to set
	 */
	public void setSpecificationinventoryDao(SpecificationInventoryDao specificationinventoryDao) {
		this.specificationinventoryDao = specificationinventoryDao;
	}

	/**
	 * @param supplierApplyDao the supplierApplyDao to set
	 */
	public void setSupplierApplyDao(ObjectDao<SupplierApply> supplierApplyDao) {
		this.supplierApplyDao = supplierApplyDao;
	}

	public void setViewPickProductDao(ObjectDao<ViewPickProduct> viewPickProductDao) {
		this.viewPickProductDao = viewPickProductDao;
	}

	/**
	 * @param virtualproductDao the virtualproductDao to set
	 */
	public void setVirtualproductDao(ObjectDao<VirtualProduct> virtualproductDao) {
		this.virtualproductDao = virtualproductDao;
	}

	private String toXML(Product product) throws CoreException {
		String xml = null;
		try {
			RemoteProduct remoteProuct = new RemoteProduct();
			BeanUtils.copyProperties(remoteProuct, product);
			List<Specification> prodSpecs = product.getSpecifications();
			List<RemoteSpecification> remoteProdSpecs = remoteProuct.getRemoteSpecifications();
			if (null != prodSpecs) {
				for (Specification spec : prodSpecs) {
					RemoteSpecification remoteSpec = new RemoteSpecification();
					BeanUtils.copyProperties(remoteSpec, spec);
					remoteProdSpecs.add(remoteSpec);
				}
				remoteProuct.setRemoteSpecifications(remoteProdSpecs);
				if ("Y".equals(product.getIsDeliverTolerance())) {
					remoteProuct.setIsDeliverTolerance("true");
				} else {
					remoteProuct.setIsDeliverTolerance("false");
				}
				if (null != product.getExpectShipDate()) {
					remoteProuct.setExpectShipDateStr(FastDateFormat.getInstance(EcConstant.PATTERN_DATE).format(
							product.getExpectShipDate()));
				}
				StringWriter sw = new StringWriter();
				BeanWriter beanWriter = new BeanWriter(sw);
				beanWriter.enablePrettyPrint();
				beanWriter.getBindingConfiguration().setMapIDs(false);
				beanWriter.write(remoteProuct);
				xml = sw.toString();
				beanWriter.flush();
				beanWriter.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new CoreException("toXML fail", e);
		}
		return xml;
	}

	@Override
	@Transactional(readOnly = false)
	public Product update(Product entity) throws CoreException {
		Product resutlt = super.update(entity);
		logService.save(getClass().getSimpleName(), "update", resutlt);
		// 商品同步
		if (isVaildSync(resutlt)) {
			batchJobService.save("ProductSyncUpdateJob", toXML(resutlt), null, resutlt.getProductId());
		}
		// 若商品销售状态为y或q时，要将n选m次商品移除&搭售的商品的启用状态设为关闭
		if (StringUtils.equalsIgnoreCase("Y", resutlt.getIsDelete())
				|| StringUtils.equalsIgnoreCase("Q", resutlt.getIsDelete())) {
			// 搭售商品金额大于等于0(加购、赠品)
			baseManager.executeHql("update AddOnProduct set isEnable = 'N' where addOnProductId = ? and addOnPrice >= 0 ",
					new Object[] { resutlt.getProductId() });
			// 移除n选m商品
			baseManager.executeHql("delete from AddOnProduct where addOnProductId = ? and addOnPrice = -1",
					new Object[] { resutlt.getProductId() });
		}
		return resutlt;
	}

	@Transactional(readOnly = false)
	public Product updateNoSync(Product entity) throws CoreException {
		Product resutlt = super.update(entity);
		logService.save(getClass().getName(), "updateProductCost", new Object[] { resutlt.getProductId(),
				resutlt.getProductCost() });
		// 若商品销售状态为y或q时，要将n选m次商品移除&搭售的商品的启用状态设为关闭
		if (StringUtils.equalsIgnoreCase("Y", resutlt.getIsDelete())
				|| StringUtils.equalsIgnoreCase("Q", resutlt.getIsDelete())) {
			// 搭售商品金额大于等于0(加购、赠品)
			baseManager.executeHql("update AddOnProduct set isEnable = 'N' where addOnProductId = ? and addOnPrice >= 0 ",
					new Object[] { resutlt.getProductId() });
			// 移除n选m商品
			baseManager.executeHql("delete from AddOnProduct where addOnProductId = ? and addOnPrice = -1",
					new Object[] { resutlt.getProductId() });
		}
		return resutlt;
	}

	@Transactional(readOnly = false)
	public Product updatePickProduct(Product entity) throws CoreException {
		Product product = getDao().update(entity);
		logService.save(getClass().getSimpleName(), "updatePickProduct", product);
		return product;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#updateProductCategory(java.lang.String[], java.lang.String,
	 * java.lang.String)
	 */

	@Transactional(readOnly = false)
	public boolean updateProductCategory(String[] id, String categoryId, String func) throws CoreException {
		try {
			if (null != id && StringUtils.isNotBlank(categoryId) && StringUtils.isNotBlank(func)) {
				ProductCategory productCategory = null;
				ProductCategory copyProductCategory = null;
				List<ProductCategory> productCategories = new ArrayList<ProductCategory>();
				CommonCriteria criteria = null;
				List<ProductCategory> datas = null;
				Category category = categoryDao.get(Long.parseLong(categoryId));
				if (null != category) {
					if (StringUtils.equalsIgnoreCase(func, "copy")) {
						for (String idstr : id) {
							productCategory = getProductcategoryDao().get(Long.parseLong(idstr));
							if (null != productCategory) {
								criteria = new CommonCriteria();
								criteria.addEq("productId", productCategory.getProductId());
								criteria.addEq("categoryId", Long.parseLong(categoryId));
								datas = getProductCategoryList(0, -1, criteria, null);
								if (datas.size() == 0) {// 已存在原本productCategory的資料不做任何處理
									copyProductCategory = new ProductCategory();
									copyProductCategory.setProductId(productCategory.getProductId());
									copyProductCategory.setShowSeq(productCategory.getShowSeq());
									copyProductCategory.setCategoryId(category.getId());
									copyProductCategory.setCategoryName(category.getName());
									copyProductCategory.setCategoryPath(category.getCategoryPath());
									productCategories.add(copyProductCategory);
								}
							}
						}
					} else if (StringUtils.equalsIgnoreCase(func, "upd")) {

						for (String idstr : id) {
							productCategory = getProductcategoryDao().get(Long.parseLong(idstr));
							if (null != productCategory) {
								criteria = new CommonCriteria();
								criteria.addEq("productId", productCategory.getProductId());
								criteria.addEq("categoryId", Long.parseLong(categoryId));
								datas = getProductCategoryList(0, -1, criteria, null);
								if (datas.size() == 0) {// 已存在原本productCategory的資料不做任何處理
									productCategory.setCategoryId(category.getId());
									productCategory.setCategoryName(category.getName());
									productCategory.setCategoryPath(category.getCategoryPath());
									productCategories.add(productCategory);
								}
							}
						}
					}
					if (productCategories.size() > 0) {
						getProductcategoryDao().saveOrUpdateBatch(productCategories);
					}
				} else {
					return false;
				}
			}
		} catch (Exception e) {
			logger.info("exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#updateProductCategory(java.lang.String[], java.lang.String[])
	 */

	@Transactional(readOnly = false)
	public boolean updateProductCategory(String[] id, String[] showSeq) throws CoreException {
		try {
			if (null != id && null != showSeq) {
				ProductCategory productCategory = null;
				List<ProductCategory> productCategories = new ArrayList<ProductCategory>();
				int i = 1;
				for (String idstr : id) {
					productCategory = getProductcategoryDao().get(Long.parseLong(idstr));
					if (null != productCategory) {
						productCategory.setShowSeq(i);
						productCategories.add(productCategory);
					}
					i++;
				}
				if (productCategories.size() > 0) {
					getProductcategoryDao().saveOrUpdateBatch(productCategories);
				}
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public BaseManager getBaseManager() {
		return baseManager;
	}

	public void setBaseManager(BaseManager baseManager) {
		this.baseManager = baseManager;
	}

	public boolean chkProductHasInventory(Product mainProduct) {
		boolean resultHasInventory = false;
		List<AddOnProduct> addonProducts = null;
		Product product = null;
		int presentCount = 0;
		SpecificationInventory presentInventory = null;
		String addonResult = "";
		// main product
		for (Specification spec : mainProduct.getSpecifications()) {
			if (!StringUtils.equalsIgnoreCase(spec.getIsDelete(), "Y")) {
				presentInventory = getSpecificationInventory(spec.getProductId(), spec.getSpecificationId());
				if (null != presentInventory) {
					presentCount = presentInventory.getAvailableInventory() + presentInventory.getCancelInventory()
							- presentInventory.getSoldInventory();
					if (presentCount > 0) {
						addonResult = addonResult + "y";
					} else {
						addonResult = addonResult + "n";
					}
				}
			}
		}
		CommonCriteria crit = null;
		crit = new CommonCriteria();
		crit.addEq("mainProductId", mainProduct.getProductId());
		crit.addEq("isDelete", "N");
		crit.addLe("startDate", new Date());
		crit.addGe("endDate", new Date());
		if (mainProduct.getProductType() != 6) {
			// get present,addonProduct
			crit.addGe("addOnPrice", new BigDecimal(0));
			crit.addEq("isEnable", "Y");
		} else {
			// get nmProduct
			crit.addEq("addOnPrice", new BigDecimal(-1));
		}
		addonProducts = getAddOnProductList(0, -1, crit, null);
		for (AddOnProduct addonProduct : addonProducts) {
			product = getDao().get(addonProduct.getAddOnProductId());
			if (!StringUtils.equalsIgnoreCase(product.getIsDelete(), "Y")
					&& !StringUtils.equalsIgnoreCase(product.getIsDelete(), "Q")
					&& !StringUtils.equalsIgnoreCase(product.getIsScm(), "Y")) {
				for (Specification spec : product.getSpecifications()) {
					if (!StringUtils.equalsIgnoreCase(spec.getIsDelete(), "Y")) {
						presentInventory = getSpecificationInventory(spec.getProductId(), spec.getSpecificationId());
						if (null != presentInventory) {
							presentCount = presentInventory.getAvailableInventory() + presentInventory.getCancelInventory()
									- presentInventory.getSoldInventory();
							if (presentCount > 0) {
								addonResult = addonResult + "y";
							} else {
								addonResult = addonResult + "n";
							}
						}
					}
				}
			}
		}
		if (StringUtils.contains(addonResult, "y")) {
			resultHasInventory = true;
		} else {
			resultHasInventory = false;
		}
		return resultHasInventory;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#saveBatchSpecification(java.util.List, java.util.List)
	 */
	@Transactional(readOnly = false)
	public void saveBatchSpecification(String productId, List<Specification> newSpecs, List<Specification> updSpecs,
			List<Specification> delSpecs) throws CoreException {
		Product product = getDao().get(productId);
		if (!newSpecs.isEmpty()) {
			specificationDao.saveOrUpdateBatch(newSpecs);
			// 新规格就新增一笔库存
			for (Specification specification : newSpecs) {
				SpecificationInventory specificationInventory = new SpecificationInventory();
				specificationInventory.setProductId(productId);
				specificationInventory.setSpecId(specification.getSpecificationId());
				specificationInventory.setAvailableInventory(0);
				specificationInventory.setCancelInventory(0);
				specificationInventory.setSoldInventory(0);
				baseManager.saveOrUpdate(specificationInventory);
			}
			product.getSpecifications().addAll(newSpecs);
		}
		if (!updSpecs.isEmpty()) {
			specificationDao.saveOrUpdateBatch(updSpecs);
		}
		if (!delSpecs.isEmpty()) {
			specificationDao.saveOrUpdateBatch(delSpecs);
		}
		if (isVaildSync(product)) {
			batchJobService.save("ProductSyncUpdateJob", toXML(product), null, product.getProductId());
		}
	}

	public Map<String, List<AddOnProductPage>> getAddonProductByMainProduct(Product product) {
		Map<String, List<AddOnProductPage>> addOnProdTypeMap = new HashMap<String, List<AddOnProductPage>>();
		StringBuffer hql = new StringBuffer(
				"select a.addOnProductId,p.productName,p.listPrice,a.addOnPrice,a.addOnDesc,p.mainCategoryID,p.mainCodeLabel,p.secondCodeLabel ");
		hql.append("from Product p,AddOnProduct a ");
		if (product.getProductType() != 6) {
			hql.append(",SpecificationInventory s ");
		}
		hql.append("where p.isDelete not in ('Y','Q') and p.productId = a.addOnProductId ");
		hql.append("and a.isDelete = 'N' and a.isEnable = 'Y' ");
		hql.append("and a.mainProductId = ? ");
		if (product.getProductType() != 6) {
			hql.append("and sysdate between a.startDate and a.endDate ");
			hql.append("and s.productId = a.addOnProductId ");
			hql.append("and s.availableInventory-s.soldInventory+s.cancelInventory >0 ");
		}
		String groupby = "group by a.addOnProductId,p.productName,p.listPrice,a.addOnPrice,a.addOnDesc,p.mainCategoryID,p.mainCodeLabel,p.secondCodeLabel ";
		String sort = "order by a.addOnProductId asc";
		AddOnProductPage addOnProductPage = null;
		if (product.getProductType() != 6) {
			Object[] presentObjs = baseManager.queryByHql(hql.toString() + " and a.addOnPrice = 0 " + groupby + sort,
					new Object[] { product.getProductId() });
			if (null != presentObjs && presentObjs.length > 0) {
				List<AddOnProductPage> presentList = new ArrayList<AddOnProductPage>();
				for (Object present : presentObjs) {
					Object[] obj = (Object[]) present;
					addOnProductPage = new AddOnProductPage();
					addOnProductPage.setAddOnProductId(obj[0].toString());
					addOnProductPage.setProductName(obj[1].toString());
					addOnProductPage.setListPrice(new BigDecimal(obj[2].toString()));
					addOnProductPage.setAddOnPrice(new BigDecimal(obj[3].toString()));
					addOnProductPage.setAddOnDesc(null != obj[4] ? obj[4].toString() : "");
					addOnProductPage.setMainCategoryID(Integer.parseInt(obj[5].toString()));
					presentList.add(addOnProductPage);
				}
				addOnProdTypeMap.put("present", presentList);
			}

			Object[] addonObjs = baseManager.queryByHql(hql.toString() + " and a.addOnPrice > 0 " + groupby + sort,
					new Object[] { product.getProductId() });
			if (null != addonObjs && addonObjs.length > 0) {
				List<AddOnProductPage> addonList = new ArrayList<AddOnProductPage>();
				for (Object addon : addonObjs) {
					Object[] obj = (Object[]) addon;
					addOnProductPage = new AddOnProductPage();
					addOnProductPage.setAddOnProductId(obj[0].toString());
					addOnProductPage.setProductName(obj[1].toString());
					addOnProductPage.setListPrice(new BigDecimal(obj[2].toString()));
					addOnProductPage.setAddOnPrice(new BigDecimal(obj[3].toString()));
					addOnProductPage.setAddOnDesc(null != obj[4] ? obj[4].toString() : "");
					addOnProductPage.setMainCategoryID(Integer.parseInt(obj[5].toString()));
					addOnProductPage.setMainCodeLabel(obj[6].toString());
					addOnProductPage.setSecondCodeLabel(obj[7].toString());
					addonList.add(addOnProductPage);
				}
				addOnProdTypeMap.put("addon", addonList);
			}
		} else {// nm
			Object[] nmObjs = baseManager.queryByHql(hql.toString() + " and a.addOnPrice = -1 " + sort,
					new Object[] { product.getProductId() });
			if (null != nmObjs && nmObjs.length > 0) {
				List<AddOnProductPage> nmList = new ArrayList<AddOnProductPage>();
				for (Object nm : nmObjs) {
					Object[] obj = (Object[]) nm;
					addOnProductPage = new AddOnProductPage();
					addOnProductPage.setAddOnProductId(obj[0].toString());
					addOnProductPage.setProductName(obj[1].toString());
					addOnProductPage.setListPrice(new BigDecimal(obj[2].toString()));
					addOnProductPage.setAddOnPrice(new BigDecimal(obj[3].toString()));
					addOnProductPage.setAddOnDesc(null != obj[4] ? obj[4].toString() : "");
					addOnProductPage.setMainCategoryID(Integer.parseInt(obj[5].toString()));
					addOnProductPage.setMainCodeLabel(obj[6].toString());
					addOnProductPage.setSecondCodeLabel(obj[7].toString());
					nmList.add(addOnProductPage);
				}
				addOnProdTypeMap.put("nm", nmList);
			}
		}
		return addOnProdTypeMap;
	}

	public Map<String, List<Specification>> getAddonProductSpecifciation(Product product) {
		Map<String, List<Specification>> specMap = new HashMap<String, List<Specification>>();
		StringBuffer hql = new StringBuffer("select distinct s from Specification s,Product p,AddOnProduct a ");
		hql.append("where s.isDelete = 'N' and s.productId = a.addOnProductId ");
		hql.append("and p.isDelete not in ('Y','Q') and p.productId = a.addOnProductId ");
		hql.append("and a.isDelete = 'N' and a.isEnable = 'Y' ");
		if (product.getProductType() != 6) {
			hql.append("and sysdate between a.startDate and a.endDate ");
		}
		hql.append("and a.mainProductId = ? ");
		Object[] objs = baseManager.queryByHql(hql.toString(), new Object[] { product.getProductId() });
		logger.info("objs:{}", objs.length);
		if (null != objs && objs.length > 0) {
			List<Specification> specList = null;
			for (Object obj : objs) {
				Specification spec = (Specification) obj;
				if (specMap.containsKey(spec.getProductId())) {
					specList = specMap.get(spec.getProductId());
				} else {
					specList = new ArrayList<Specification>();
				}
				specList.add(spec);
				specMap.put(spec.getProductId(), specList);
			}
		}
		return specMap;
	}

	public Map<String, List<SpecificationMajor>> getAddonProductSpecificationMajor(Product product) {
		Map<String, List<SpecificationMajor>> specMap = new HashMap<String, List<SpecificationMajor>>();
		StringBuffer hql = new StringBuffer("select s from SpecificationMajor s,Product p,AddOnProduct a ");
		hql.append("where s.isDelete = 'N' and s.productId = a.addOnProductId ");
		hql.append("and p.isDelete not in ('Y','Q') and p.productId = a.addOnProductId ");
		hql.append("and a.isDelete = 'N' and a.isEnable = 'Y' ");
		if (product.getProductType() != 6) {
			hql.append("and sysdate between a.startDate and a.endDate ");
		}
		hql.append("and a.mainProductId = ? ");
		Object[] objs = baseManager.queryByHql(hql.toString(), new Object[] { product.getProductId() });
		logger.info("objs:{}", objs.length);
		if (null != objs && objs.length > 0) {
			List<SpecificationMajor> specList = null;
			for (Object obj : objs) {
				SpecificationMajor spec = (SpecificationMajor) obj;
				if (specMap.containsKey(spec.getProductId())) {
					specList = specMap.get(spec.getProductId());
				} else {
					specList = new ArrayList<SpecificationMajor>();
				}
				specList.add(spec);
				specMap.put(spec.getProductId(), specList);
			}
		}
		return specMap;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getAddonProductInvByMainProduct(java.lang.String)
	 */

	public Map<String, Map<Long, Integer>> getAddonProductInvByMainProduct(Product product) {
		StringBuffer hql = new StringBuffer();
		hql
				.append("select si.specId,(si.availableInventory+si.cancelInventory-si.soldInventory) as saleCount,a.addOnPrice ");
		hql.append("from SpecificationInventory si,Specification s,Product p,AddOnProduct a ");
		hql.append("where si.specId = s.specificationId and si.productId = s.productId and s.isDelete = 'N' ");
		hql.append("and p.isDelete not in ('Y','Q') and p.productId = a.addOnProductId ");
		hql.append("and a.isDelete = 'N' and a.isEnable = 'Y' and s.productId = a.addOnProductId ");
		if (product.getProductType() == 6) {
			hql.append("and a.addOnPrice = -1 ");
		} else {
			hql.append("and sysdate between a.startDate and a.endDate ");
			hql.append("and a.addOnPrice >= 0 ");
		}
		hql.append("and a.mainProductId = ? ");
		Object[] addonInvs = baseManager.queryByHql(hql.toString(), new Object[] { product.getProductId() });
		Map<String, Map<Long, Integer>> prodTypeInvMap = new HashMap<String, Map<Long, Integer>>();
		if (null != addonInvs && addonInvs.length > 0) {
			Object[] addonInvObj = null;
			if (product.getProductType() == 6) {// n选m
				Map<Long, Integer> nmInvMap = new HashMap<Long, Integer>();
				for (Object addonInv : addonInvs) {
					addonInvObj = (Object[]) addonInv;
					nmInvMap.put(Long.parseLong(addonInvObj[0].toString()), Integer.parseInt(addonInvObj[1].toString()));
				}
				if (nmInvMap.size() > 0) {
					prodTypeInvMap.put("nm", nmInvMap);
				}
			} else {
				Map<Long, Integer> addonInvMap = new HashMap<Long, Integer>();
				Map<Long, Integer> presentInvMap = new HashMap<Long, Integer>();
				for (Object addonInv : addonInvs) {
					addonInvObj = (Object[]) addonInv;
					if (Float.valueOf(addonInvObj[2].toString()) == 0) {// 赠品
						presentInvMap.put(Long.parseLong(addonInvObj[0].toString()), Integer.parseInt(addonInvObj[1].toString()));
					} else {
						addonInvMap.put(Long.parseLong(addonInvObj[0].toString()), Integer.parseInt(addonInvObj[1].toString()));
					}
				}
				if (presentInvMap.size() > 0) {
					prodTypeInvMap.put("present", presentInvMap);
				}
				if (addonInvMap.size() > 0) {
					prodTypeInvMap.put("addon", addonInvMap);
				}
			}
		}
		return prodTypeInvMap;
	}

	@Transactional(readOnly = false)
	public String updateProductCostArray(String[] productId, BigDecimal cost[]) throws CoreException {
		String isSuccess = "true";
		String errProductId = "";
		BigDecimal errCost = new BigDecimal("0");
		try {
			for (int i = 0; i < productId.length; i++) {
				errProductId = productId[i];
				errCost = cost[i];
				Product entity = getDao().get(productId[i]);
				if (entity == null) {
					return "[ERROR_updateProductCostArray]查无此商品:" + errProductId;
				}
				entity.setProductCost(cost[i]);
				Product resutlt = super.update(entity);
				logService.save(getClass().getName(), "updateProductCost", new Object[] { resutlt.getProductId(), cost[i] });
			}
		} catch (Exception e) {
			// logger.error("ERROR_updateProductCostArray productId:", e);
			isSuccess = "[ERROR_updateProductCostArray]productId:" + errProductId + " productCost:" + errCost;
		}
		return isSuccess;
	}

	@Override
	public List<Product> getList(int firstResult, int maxResults, CommonCriteria criteria, String[] sortOrder)
			throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "category.categoryPath");// 分線維護權限檢核
		return super.getList(firstResult, maxResults, critInRlike, sortOrder);
	}

	@Override
	public Number getListSize(CommonCriteria criteria) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "category.categoryPath");// 分線維護權限檢核
		return super.getListSize(critInRlike);
	}

	/**
	 * 分線維護權限檢核
	 * 
	 * @param commcriteria
	 * @return
	 */
	CriteriaInRlike mergeCritInRlike(CommonCriteria criteria, String tableParam) {
		CriteriaInRlike critInRlike = null;
		User user = AdminHelper.getUser();
		if (null != user) {
			if (null == criteria) {
				criteria = new CommonCriteria();
			}
			critInRlike = new CriteriaInRlike(criteria);
			// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
			List<Serializable> prs = new ArrayList<Serializable>();
			for (UserPermission up : user.getPermissions(Type.CATEGORY).values()) {
				prs.add(up.getPermissionCode() + STRING_SYMBOL);
			}
			critInRlike.addInRlike(tableParam, prs);
		} else {
			if (null == criteria) {
				criteria = new CommonCriteria();
			}
			critInRlike = new CriteriaInRlike(criteria);
		}
		return critInRlike;
	}

	/**
	 * 分線維護權限檢核
	 * 
	 * @param parentId
	 * @return
	 */
	String mergeHqlInRlike(String tableParam) {
		String premissString = "";
		User user = AdminHelper.getUser();
		if (null != user) {
			StringBuffer sb = new StringBuffer();
			// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
			if (user.getPermissions(Type.CATEGORY).size() > 0) {
				sb.append("and ( ");
				int i = 0;
				for (UserPermission up : user.getPermissions(Type.CATEGORY).values()) {
					sb.append(tableParam).append(" like '").append(up.getPermissionCode()).append(STRING_SYMBOL).append("%'");
					if (i != user.getPermissions(Type.CATEGORY).size() - 1) {
						sb.append(" or ");
					}
					i++;
				}
				sb.append(" ) ");
				premissString = sb.toString();
				sb.setLength(0);
			}
		}
		return premissString;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#updateProductIsScmToBOBatch(java.lang.String)
	 */

	public boolean updateIsScmToBOBatch(String supplierId) throws CoreException {
		Object[] productIds = baseManager.queryByHql("select productId from Product where supplierId = ? and isScm = 'Y'",
				new Object[] { supplierId });
		int base = 980;
		int t = 0;
		StringBuffer sb = new StringBuffer();
		if (!ArrayUtils.isEmpty(productIds)) {
			if (productIds.length <= base) {
				t = 0;
				for (Object productId : productIds) {
					sb.append("'").append(productId).append("'");
					if (t < productIds.length - 1) {
						sb.append(",");
					}
					t++;
				}
				baseManager.executeHql("update Product set isScm='B' where productId in ( " + sb.toString() + " )",
						new Object[] {});
				sb.setLength(0);
			} else {
				int count = new BigDecimal(String.valueOf(productIds.length)).divide(new BigDecimal(String.valueOf(base)),
						BigDecimal.ROUND_UP).intValue();
				int j = 1;
				for (int i = 0; i < count; i++) {
					Object[] tmpProductIds = ArrayUtils.subarray(productIds, i * base,
							base * j > productIds.length ? productIds.length : (base * j));
					t = 0;
					for (Object productId : tmpProductIds) {
						sb.append("'").append(productId).append("'");
						if (t < tmpProductIds.length - 1) {
							sb.append(",");
						}
						t++;
					}
					baseManager.executeHql("update Product set isScm='B' where productId in ( " + sb.toString() + " )",
							new Object[] {});
					j++;
					sb.setLength(0);
				}
			}
			batchJobService.save("SyncProductIsScm", ArrayUtils.toString(productIds).replace("{", "").replace("}", ""), null,
					supplierId);
		}
		return true;
	}

	public List<Object> orderNotShipping(String productId, String specId) throws Exception {
		StringBuffer sb = new StringBuffer();
		List attrs = new ArrayList();
		sb.append("select b.orderSt,count(a.qty) from OrderProductDetail a,Orders b ");
		sb.append("where b.orderId = a.orderId ");
		sb.append("and b.orderSt in ('00','10','20','25') ");
		sb.append("and a.prodSpecId=? ");
		sb.append("and a.prodId=? ");
		sb.append("group by b.orderSt ");
		attrs.add(specId);
		attrs.add(productId);
		List<Object> lists = getDao().getQueryByList(sb.toString(), attrs, 0, -1);
		return lists;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductPageableList(java.util.Map, int, int)
	 */

	public List<Product> getProductPageableList(Map<String, String> searchMap, int firstResult, int maxResults)
			throws CoreException {
		Map<String, Object> attrs = new HashMap<String, Object>();
		StringBuilder sb = new StringBuilder("");
		sb.append("select p from Product p ");
		sb.append("where p.productType != '6' ");
		if (StringUtils.isNotBlank(searchMap.get("productId"))) {
			String[] temps = StringUtils.split(searchMap.get("productId"), ",");
			StringBuffer tempStr = new StringBuffer("");
			for (String temp : temps) {
				tempStr.append("'").append(temp).append("'").append(",");
			}
			sb.append("and p.productId in ( ").append(tempStr.substring(0, tempStr.length() - 1)).append(" )");
		}

		if (StringUtils.isNotBlank(searchMap.get("productName"))) {
			sb.append("and p.productName like :productName ");
			attrs.put("productName", searchMap.get("productName") + "%");
		}

		if (StringUtils.isNotBlank(searchMap.get("isDelete"))) {
			sb.append("and p.isDelete = :isDelete ");
			attrs.put("isDelete", searchMap.get("isDelete"));
		}

		if (StringUtils.isNotBlank(searchMap.get("productType"))) {
			sb.append("and p.productType = :productType ");
			attrs.put("productType", Integer.parseInt(searchMap.get("productType")));
		}

		if (StringUtils.isNotBlank(searchMap.get("supplierId"))) {// 供应商搜寻包含台湾馆供应商也要找
			sb.append("and ( p.supplierId = :supplierId or p.twSupplierId = :supplierId ) ");
			attrs.put("supplierId", searchMap.get("supplierId"));
		}

		if (StringUtils.isNotBlank(searchMap.get("categoryPath"))) {
			sb.append("and p.category.categoryPath like :categoryPath ");
			attrs.put("categoryPath", searchMap.get("categoryPath") + "%");
			logger.info("categoryPath:{}", attrs.get("categoryPath"));
		}

		if (StringUtils.isNotBlank(searchMap.get("productBrand"))) {
			sb.append("and p.productBrand = :productBrand ");
			attrs.put("productBrand", searchMap.get("productBrand"));
		}

		if (StringUtils.isNotBlank(searchMap.get("dataSrc"))) {
			sb.append("and p.dataSrc = :dataSrc ");
			attrs.put("dataSrc", searchMap.get("dataSrc"));
		}

		if (StringUtils.isNotBlank(searchMap.get("isScm"))) {
			sb.append("and p.isScm = :isScm ");
			attrs.put("isScm", searchMap.get("isScm"));
		}

		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分線維護權限檢核
		sb.append("order by p.productId desc ");
		List<Product> products = getDao().getQueryByMap(sb.toString(), attrs, firstResult, maxResults);
		sb.setLength(0);
		return products;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductPageableListSize(java.util.Map)
	 */

	public Number getProductPageableListSize(Map<String, String> searchMap) throws CoreException {
		Map<String, Object> attrs = new HashMap<String, Object>();
		StringBuilder sb = new StringBuilder("");
		sb.append("select count(p.productId) from Product p ");
		sb.append("where p.productType != '6' ");
		if (StringUtils.isNotBlank(searchMap.get("productId"))) {
			String[] temps = StringUtils.split(searchMap.get("productId"), ",");
			StringBuffer tempStr = new StringBuffer("");
			for (String temp : temps) {
				tempStr.append("'").append(temp).append("'").append(",");
			}
			sb.append("and p.productId in ( ").append(tempStr.substring(0, tempStr.length() - 1)).append(" )");
		}

		if (StringUtils.isNotBlank(searchMap.get("productName"))) {
			sb.append("and p.productName like :productName ");
			attrs.put("productName", searchMap.get("productName") + "%");
		}

		if (StringUtils.isNotBlank(searchMap.get("isDelete"))) {
			sb.append("and p.isDelete = :isDelete ");
			attrs.put("isDelete", searchMap.get("isDelete"));
		}

		if (StringUtils.isNotBlank(searchMap.get("productType"))) {
			sb.append("and p.productType = :productType ");
			attrs.put("productType", Integer.parseInt(searchMap.get("productType")));
		}

		if (StringUtils.isNotBlank(searchMap.get("supplierId"))) {// 供应商搜寻包含台湾馆供应商也要找
			sb.append("and ( p.supplierId = :supplierId or p.twSupplierId = :supplierId ) ");
			attrs.put("supplierId", searchMap.get("supplierId"));
		}

		if (StringUtils.isNotBlank(searchMap.get("categoryPath"))) {
			sb.append("and p.category.categoryPath like :categoryPath ");
			attrs.put("categoryPath", searchMap.get("categoryPath") + "%");
		}

		if (StringUtils.isNotBlank(searchMap.get("productBrand"))) {
			sb.append("and p.productBrand = :productBrand ");
			attrs.put("productBrand", searchMap.get("productBrand"));
		}

		if (StringUtils.isNotBlank(searchMap.get("dataSrc"))) {
			sb.append("and p.dataSrc = :dataSrc ");
			attrs.put("dataSrc", searchMap.get("dataSrc"));
		}

		if (StringUtils.isNotBlank(searchMap.get("isScm"))) {
			sb.append("and p.isScm = :isScm ");
			attrs.put("isScm", searchMap.get("isScm"));
		}

		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分線維護權限檢核
		int productsSize = Integer.parseInt(getDao().getQueryByMap(sb.toString(), attrs, 0, -1).get(0).toString());
		sb.setLength(0);
		return productsSize;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductAttrListSize(java.util.List, java.lang.String,
	 * java.lang.String, java.util.Map, boolean)
	 */

	public Number getProductAttrListSize(List productIds, String productName, String sort_promoteName,
			String categoryPath, Map eqData, Map neData, Map inData, Boolean hasShelf) throws CoreException {
		List objs = new ArrayList();
		StringBuffer hql = new StringBuffer();
		hql.append("select count(*)");

		hql.append(getProductAttrHql(productIds, productName, sort_promoteName, categoryPath, eqData, neData, inData,
				hasShelf, objs));

		List result = getDao().getQueryByList(hql.toString(), objs, 0, -1);
		if (result != null && result.size() > 0 && result.get(0) instanceof Number) {
			return (Number) result.get(0);
		} else {
			return 0L;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getProductAttrList(java.util.List, java.lang.String,
	 * java.lang.String, java.util.Map, boolean, java.util.List, int, int)
	 */

	public List<Object[]> getProductAttrList(List productIds, String productName, String categoryPath, Map eqData,
			Map neData, Map inData, Boolean hasShelf, int firstResult, int maxResults, String[] sortBy) throws CoreException {
		List objs = new ArrayList();
		StringBuffer hql = new StringBuffer();
		hql.append("select vs.shelfPrice, p");

		hql.append(getProductAttrHql(productIds, productName, null, categoryPath, eqData, neData, inData, hasShelf, objs));
		if (sortBy != null) {
			StringBuffer sort = new StringBuffer();
			for (String s : sortBy) {
				if (sort.length() == 0) {
					sort.append("p." + s);
				} else {
					sort.append(",p." + s);
				}
			}
			hql.append(" order by ").append(sort);
		}
		List result = getDao().getQueryByList(hql.toString(), objs, firstResult, maxResults);
		return result;
	}

	public List<Object[]> getProductAttrListForShelf(List productIds, String productName, String sort_promoteName,
			String categoryPath, Map eqData, Map neData, Map inData, Boolean hasShelf, int firstResult, int maxResults,
			String[] sortBy) throws CoreException {
		List objs = new ArrayList();
		StringBuffer hql = new StringBuffer();
		hql.append("select vs , p");

		hql.append(getProductAttrHql(productIds, productName, sort_promoteName, categoryPath, eqData, neData, inData,
				hasShelf, objs));
		if (sortBy != null) {
			StringBuffer sort = new StringBuffer();
			for (String s : sortBy) {
				if (sort.length() == 0) {
					sort.append(s);
				} else {
					sort.append("," + s);
				}
			}
			hql.append(" order by ").append(sort);
		}
		List result = getDao().getQueryByList(hql.toString(), objs, firstResult, maxResults);
		return result;
	}

	private String getProductAttrHql(List<String> productIds, String productName, String sort_promoteName,
			String categoryPath, Map<String, Serializable> eqData, Map<String, Serializable> neData,
			Map<String, Collection> inData, Boolean hasShelf, List objs) {
		StringBuffer hql = new StringBuffer();
		hql.append(" from Product p left join p.viewShelf vs where 1=1");
		if (productIds != null && productIds.size() > 0) {
			StringBuffer in = new StringBuffer();
			for (String s : productIds) {
				if (in.length() == 0) {
					in.append("?");
				} else {
					in.append(",?");
				}
				objs.add(s);
			}
			hql.append(" and p.productId in (").append(in.toString()).append(")");
		}
		if (StringUtils.isNotBlank(productName)) {
			hql.append(" and p.productName like ?");
			objs.add("%" + productName + "%");
		}
		if (StringUtils.isNotBlank(sort_promoteName)) {
			hql.append(" and vs.promoteName like ?");
			objs.add("%" + sort_promoteName + "%");
		}
		if (StringUtils.isNotBlank(categoryPath)) {
			hql.append(" and (p.mainCategoryPath like ?");
			if (categoryPath.endsWith("/")) {
				objs.add(categoryPath + "%");
				hql.append(" or p.mainCategoryPath = ?)");
				objs.add(categoryPath.substring(0, categoryPath.length() - 1));
			} else {
				objs.add(categoryPath + "/%");
				hql.append(" or p.mainCategoryPath = ?)");
				objs.add(categoryPath);
			}
		}
		if (eqData != null) {
			for (String s : eqData.keySet()) {
				hql.append(" and p.").append(s).append(" = ?");
				objs.add(eqData.get(s));
			}
		}
		if (neData != null) {
			for (String s : neData.keySet()) {
				hql.append(" and p.").append(s).append(" != ?");
				objs.add(neData.get(s));
			}
		}
		if (inData != null) {
			for (String s : inData.keySet()) {
				StringBuffer in = new StringBuffer();
				Collection<Serializable> c = inData.get(s);
				if (c != null) {
					for (Serializable t : c) {
						if (in.length() == 0) {
							in.append("?");
						} else {
							in.append(",?");
						}
						objs.add(t);
					}
				}
				hql.append(" and p.").append(s).append(" in (").append(in.toString()).append(")");
			}
		}
		if (hasShelf != null) {
			if (hasShelf.booleanValue()) {
				hql.append(" and vs.shelfId is not null ");
			} else {
				hql.append(" and vs.shelfId is null ");
			}
		}
		hql.append(mergeHqlInRlike("p.category.categoryPath"));// 分线维护权限检核
		return hql.toString();
	}

	public void setProductPageDao(ObjectDao<ProductPage> productPageDao) {
		this.productPageDao = productPageDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#getAddOnProductListSize(java.lang.String, java.lang.String,
	 * java.lang.String)
	 */

	public Number getAddOnProductListSize(String mainProductId, String addOnProductId, String status)
			throws CoreException {
		return addonproductDao.getAddOnProductListSize(mainProductId, addOnProductId, status);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.product.service.ProductService#checkIsSoldOut(java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void checkIsSoldOut(String productId) throws CoreException {
		if (StringUtils.isNotBlank(productId)) {
			Object[] isSoldOut = baseManager
					.queryByHql(
							"select count(*) from SpecificationInventory a,Specification b,Product c where a.productId=? and a.productId=c.productId and c.productType!='6' and (a.availableInventory + a.cancelInventory - a.soldInventory) >0 and a.specId=b.specificationId and b.isDelete='N' ",
							new Object[] { productId });
			Product product = this.get(productId);
			if (((Number) isSoldOut[0]).intValue() == 0 && product.getProductType() != 6) {
				if (!"Y".equals(product.getIsSoldOut())) {
					product.setIsSoldOut("Y");
					super.save(product);
				}
			} else {
				if (!"N".equals(product.getIsSoldOut())) {
					product.setIsSoldOut("N");
					super.save(product);
				}
			}
		}
	}

}